diff --git a/vita3k/config/include/config/config.h b/vita3k/config/include/config/config.h index 49661ee1..e6a74b28 100644 --- a/vita3k/config/include/config/config.h +++ b/vita3k/config/include/config/config.h @@ -51,8 +51,6 @@ code(bool, "discord-rich-presence", true, discord_rich_presence) \ code(bool, "wait-for-debugger", false, wait_for_debugger) \ code(bool, "color-surface-debug", false, color_surface_debug) \ - code(bool, "hardware-flip", false, hardware_flip) \ - code(bool, "use-ubo", false, use_ubo) \ code(bool, "performance-overlay", false, performance_overlay) \ code(std::string, "backend-renderer", "OpenGL", backend_renderer) \ code(int, "keyboard-button-select", 229, keyboard_button_select) \ diff --git a/vita3k/features/include/features/state.h b/vita3k/features/include/features/state.h index 371de5df..5d9c18f0 100644 --- a/vita3k/features/include/features/state.h +++ b/vita3k/features/include/features/state.h @@ -6,8 +6,6 @@ struct FeatureState { bool support_shader_interlock = false; ///< First option for blending. Using this with ordered execution mode. bool support_texture_barrier = false; ///< Second option for blending. Slower but work on 3 vendors. bool direct_fragcolor = false; - bool hardware_flip = true; ///< Allow flipping in shader. - bool use_ubo = false; bool use_shader_binding = false; bool is_programmable_blending_supported() const { diff --git a/vita3k/gui/src/settings_dialog.cpp b/vita3k/gui/src/settings_dialog.cpp index d459bfb3..dba1cfdb 100644 --- a/vita3k/gui/src/settings_dialog.cpp +++ b/vita3k/gui/src/settings_dialog.cpp @@ -193,9 +193,6 @@ void draw_settings_dialog(GuiState &gui, HostState &host) { ImGui::PushStyleColor(ImGuiCol_Text, GUI_COLOR_TEXT_MENUBAR); if (ImGui::BeginTabItem("GPU")) { ImGui::PopStyleColor(); - ImGui::Checkbox("Hardware Flip", &host.cfg.hardware_flip); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("Check the box to enable texture flipping from GPU side.\nIt is recommended to disable this option for homebrew."); ImGui::EndTabItem(); } else ImGui::PopStyleColor(); diff --git a/vita3k/interface.cpp b/vita3k/interface.cpp index 1fd6bc1a..929e0cf1 100644 --- a/vita3k/interface.cpp +++ b/vita3k/interface.cpp @@ -310,7 +310,6 @@ static ExitCode load_app_impl(Ptr &entry_point, HostState &host, con return InitConfigFailed; } - LOG_INFO_IF(host.cfg.hardware_flip, "{}: enabled", host.cfg[e_hardware_flip]); LOG_INFO("ngs experimental state: {}", !host.cfg.disable_ngs); LOG_INFO("video player state: {}", host.cfg.video_playing); if (host.cfg.auto_lle) diff --git a/vita3k/main.cpp b/vita3k/main.cpp index 72505962..b459c08e 100644 --- a/vita3k/main.cpp +++ b/vita3k/main.cpp @@ -206,7 +206,6 @@ int main(int argc, char *argv[]) { } gui::init_app_background(gui, host, host.io.title_id); - host.renderer->features.hardware_flip = host.cfg.hardware_flip; app::gl_screen_renderer gl_renderer; diff --git a/vita3k/modules/SceGxm/SceGxm.cpp b/vita3k/modules/SceGxm/SceGxm.cpp index 6fe7e98d..f4e8ec6c 100644 --- a/vita3k/modules/SceGxm/SceGxm.cpp +++ b/vita3k/modules/SceGxm/SceGxm.cpp @@ -743,16 +743,8 @@ EXPORT(int, sceGxmDraw, SceGxmContext *context, SceGxmPrimitiveType primType, Sc const SceGxmProgram &vertex_program_gxp = *gxm_vertex_program.program.get(host.mem); const SceGxmProgram &fragment_program_gxp = *gxm_fragment_program.program.get(host.mem); - if (host.renderer->features.use_ubo) { - renderer::set_uniform_buffers(*host.renderer, context->renderer.get(), vertex_program_gxp, context->state.vertex_uniform_buffers, gxm_vertex_program.renderer_data->uniform_buffer_sizes, host.mem); - renderer::set_uniform_buffers(*host.renderer, context->renderer.get(), fragment_program_gxp, context->state.fragment_uniform_buffers, gxm_fragment_program.renderer_data->uniform_buffer_sizes, host.mem); - } else { - // Update uniforms from this side. We should pass the pointer to parameter struct, since from there it can - // find the name and other things based on the pointer in memory. The pointer should be persists until - // the fragment is done, so we are guranteed to be safe. - renderer::set_uniforms(*host.renderer, context->renderer.get(), vertex_program_gxp, context->state.vertex_uniform_buffers, host.mem); - renderer::set_uniforms(*host.renderer, context->renderer.get(), fragment_program_gxp, context->state.fragment_uniform_buffers, host.mem); - } + renderer::set_uniform_buffers(*host.renderer, context->renderer.get(), vertex_program_gxp, context->state.vertex_uniform_buffers, gxm_vertex_program.renderer_data->uniform_buffer_sizes, host.mem); + renderer::set_uniform_buffers(*host.renderer, context->renderer.get(), fragment_program_gxp, context->state.fragment_uniform_buffers, gxm_fragment_program.renderer_data->uniform_buffer_sizes, host.mem); // Update vertex data. We should stores a copy of the data to pass it to GPU later, since another scene // may start to overwrite stuff when this scene is being processed in our queue (in case of OpenGL). @@ -837,13 +829,8 @@ EXPORT(int, sceGxmDrawPrecomputed, SceGxmContext *context, SceGxmPrecomputedDraw const SceGxmProgram &vertex_program_gxp = *vertex_program->program.get(host.mem); const SceGxmProgram &fragment_program_gxp = *fragment_program->program.get(host.mem); - if (host.renderer->features.use_ubo) { - renderer::set_uniform_buffers(*host.renderer, context->renderer.get(), vertex_program_gxp, *vertex_state->uniform_buffers.get(host.mem), gxm_vertex_program.renderer_data->uniform_buffer_sizes, host.mem); - renderer::set_uniform_buffers(*host.renderer, context->renderer.get(), fragment_program_gxp, *fragment_state->uniform_buffers.get(host.mem), gxm_fragment_program.renderer_data->uniform_buffer_sizes, host.mem); - } else { - renderer::set_uniforms(*host.renderer, context->renderer.get(), vertex_program_gxp, *vertex_state->uniform_buffers.get(host.mem), host.mem); - renderer::set_uniforms(*host.renderer, context->renderer.get(), fragment_program_gxp, *fragment_state->uniform_buffers.get(host.mem), host.mem); - } + renderer::set_uniform_buffers(*host.renderer, context->renderer.get(), vertex_program_gxp, *vertex_state->uniform_buffers.get(host.mem), gxm_vertex_program.renderer_data->uniform_buffer_sizes, host.mem); + renderer::set_uniform_buffers(*host.renderer, context->renderer.get(), fragment_program_gxp, *fragment_state->uniform_buffers.get(host.mem), gxm_fragment_program.renderer_data->uniform_buffer_sizes, host.mem); // Update vertex data. We should stores a copy of the data to pass it to GPU later, since another scene // may start to overwrite stuff when this scene is being processed in our queue (in case of OpenGL). diff --git a/vita3k/renderer/include/renderer/gl/functions.h b/vita3k/renderer/include/renderer/gl/functions.h index 4e493e67..1f310bac 100644 --- a/vita3k/renderer/include/renderer/gl/functions.h +++ b/vita3k/renderer/include/renderer/gl/functions.h @@ -54,18 +54,18 @@ bool create(std::unique_ptr &context); bool create(std::unique_ptr &rt, const SceGxmRenderTargetParams ¶ms, const FeatureState &features); bool create(std::unique_ptr &fp, GLState &state, const SceGxmProgram &program, const SceGxmBlendInfo *blend, GXPPtrMap &gxp_ptr_map, const char *base_path, const char *title_id); bool create(std::unique_ptr &vp, GLState &state, const SceGxmProgram &program, GXPPtrMap &gxp_ptr_map, const char *base_path, const char *title_id); -bool sync_state(GLContext &context, const GxmContextState &state, const MemState &mem, bool enable_texture_cache, bool hardware_flip, const std::string &base_path, const std::string &title_id); +bool sync_state(GLContext &context, const GxmContextState &state, const MemState &mem, bool enable_texture_cache, const std::string &base_path, const std::string &title_id); void sync_rendertarget(const GLRenderTarget &rt); void set_context(GLContext &ctx, GxmContextState &state, const MemState &mem, const GLRenderTarget *rt, const FeatureState &features); -void get_surface_data(GLContext &context, size_t width, size_t height, size_t stride_in_pixels, uint32_t *pixels, SceGxmColorFormat format, const bool do_flip); +void get_surface_data(GLContext &context, size_t width, size_t height, size_t stride_in_pixels, uint32_t *pixels, SceGxmColorFormat format); void draw(GLState &renderer, GLContext &context, GxmContextState &state, const FeatureState &features, SceGxmPrimitiveType type, SceGxmIndexFormat format, const void *indices, size_t count, const MemState &mem, const char *base_path, const char *title_id, const Config &config); void upload_vertex_stream(GLContext &context, const std::size_t stream_index, const std::size_t length, const void *data); // State -void sync_viewport(GLContext &context, const GxmContextState &state, const bool hardware_flip); -void sync_clipping(GLContext &context, const GxmContextState &state, const bool hardware_flip); +void sync_viewport(GLContext &context, const GxmContextState &state); +void sync_clipping(GLContext &context, const GxmContextState &state); void sync_cull(GLContext &context, const GxmContextState &state); void sync_front_depth_func(const GxmContextState &state); void sync_front_depth_write_enable(const GxmContextState &state); diff --git a/vita3k/renderer/src/gl/draw.cpp b/vita3k/renderer/src/gl/draw.cpp index f497cf6f..d941f890 100644 --- a/vita3k/renderer/src/gl/draw.cpp +++ b/vita3k/renderer/src/gl/draw.cpp @@ -125,39 +125,12 @@ void draw(GLState &renderer, GLContext &context, GxmContextState &state, const F } bind_host_texture("f_mask", shader::MASK_TEXTURE_SLOT_IMAGE, context.render_target->masktexture[0]); - if (!features.use_ubo) { - const SceGxmVertexProgram &gxm_vertex_program = *state.vertex_program.get(mem); - const FragmentProgram &fragment_program = *gxm_fragment_program.renderer_data.get(); + // Try to configure the vertex shader, to output coordinates suited for GXM viewport + GLuint flip_vec_loc = glGetUniformLocation(program_id, "flip_vec"); - // Set uniforms - const SceGxmProgram &vertex_program_gxp = *gxm_vertex_program.program.get(mem); - - gl::GLShaderStatics &vertex_gl_statics = reinterpret_cast(gxm_vertex_program.renderer_data.get())->statics; - gl::GLShaderStatics &fragment_gl_statics = reinterpret_cast(gxm_fragment_program.renderer_data.get())->statics; - - for (auto &vertex_uniform : context.vertex_set_requests) { - gl::set_uniform(program_id, vertex_program_gxp, vertex_gl_statics, mem, vertex_uniform.parameter, vertex_uniform.data, - config.log_uniforms); - - delete vertex_uniform.data; - } - - for (auto &fragment_uniform : context.fragment_set_requests) { - gl::set_uniform(program_id, fragment_program_gxp, fragment_gl_statics, mem, fragment_uniform.parameter, - fragment_uniform.data, config.log_uniforms); - - delete fragment_uniform.data; - } - } - - if (config.hardware_flip) { - // Try to configure the vertex shader, to output coordinates suited for GXM viewport - GLuint flip_vec_loc = glGetUniformLocation(program_id, "flip_vec"); - - if (flip_vec_loc != -1) { - // Let's do flipping - glUniform4fv(flip_vec_loc, 1, context.viewport_flip); - } + if (flip_vec_loc != -1) { + // Let's do flipping + glUniform4fv(flip_vec_loc, 1, context.viewport_flip); } const auto set_uniform_if_exists = [&](const std::string &name, float val) { diff --git a/vita3k/renderer/src/gl/renderer.cpp b/vita3k/renderer/src/gl/renderer.cpp index e7ea4b1a..6fefda5c 100644 --- a/vita3k/renderer/src/gl/renderer.cpp +++ b/vita3k/renderer/src/gl/renderer.cpp @@ -270,8 +270,6 @@ bool create(SDL_Window *window, std::unique_ptr &state) { LOG_WARN("Consider updating your graphics drivers or upgrading your GPU."); } - gl_state.features.use_ubo = true; - return true; } @@ -438,20 +436,7 @@ void set_context(GLContext &context, GxmContextState &state, const MemState &mem } } -static void flip_vertically(uint32_t *pixels, size_t width, size_t height, size_t stride_in_pixels) { - R_PROFILE(__func__); - - uint32_t *row1 = &pixels[0]; - uint32_t *row2 = &pixels[(height - 1) * stride_in_pixels]; - - while (row1 < row2) { - std::swap_ranges(&row1[0], &row1[width], &row2[0]); - row1 += stride_in_pixels; - row2 -= stride_in_pixels; - } -} - -void get_surface_data(GLContext &context, size_t width, size_t height, size_t stride_in_pixels, uint32_t *pixels, SceGxmColorFormat format, const bool do_flip) { +void get_surface_data(GLContext &context, size_t width, size_t height, size_t stride_in_pixels, uint32_t *pixels, SceGxmColorFormat format) { R_PROFILE(__func__); if (pixels == nullptr) { @@ -504,11 +489,6 @@ void get_surface_data(GLContext &context, size_t width, size_t height, size_t st } glPixelStorei(GL_PACK_ROW_LENGTH, 0); - - if (do_flip) { - flip_vertically(pixels, width, height, stride_in_pixels); - } - ++context.texture_cache.timestamp; } diff --git a/vita3k/renderer/src/gl/sync_state.cpp b/vita3k/renderer/src/gl/sync_state.cpp index 0c16fbd3..f72409b5 100644 --- a/vita3k/renderer/src/gl/sync_state.cpp +++ b/vita3k/renderer/src/gl/sync_state.cpp @@ -117,7 +117,7 @@ void sync_mask(GLContext &context, const GxmContextState &state, const MemState glBindTexture(GL_TEXTURE_2D, texId); } -void sync_viewport(GLContext &context, const GxmContextState &state, const bool hardware_flip) { +void sync_viewport(GLContext &context, const GxmContextState &state) { // Viewport. const GLsizei display_w = state.color_surface.width; const GLsizei display_h = state.color_surface.height; @@ -131,34 +131,30 @@ void sync_viewport(GLContext &context, const GxmContextState &state, const bool const GLfloat x = viewport.offset.x - std::abs(viewport.scale.x); const GLfloat y = std::min(ymin, ymax); - if (hardware_flip) { - context.viewport_flip[0] = 1.0f; - context.viewport_flip[1] = (ymin < ymax) ? -1.0f : 1.0f; - context.viewport_flip[2] = 1.0f; - context.viewport_flip[3] = 1.0f; - } + context.viewport_flip[0] = 1.0f; + context.viewport_flip[1] = (ymin < ymax) ? -1.0f : 1.0f; + context.viewport_flip[2] = 1.0f; + context.viewport_flip[3] = 1.0f; - glViewportIndexedf(0, x, hardware_flip ? y : display_h - h - y, w, h); + glViewportIndexedf(0, x, y, w, h); glDepthRange(viewport.offset.z - viewport.scale.z, viewport.offset.z + viewport.scale.z); } else { - if (hardware_flip) { - context.viewport_flip[0] = 1.0f; - context.viewport_flip[1] = -1.0f; - context.viewport_flip[2] = 1.0f; - context.viewport_flip[3] = 1.0f; - } + context.viewport_flip[0] = 1.0f; + context.viewport_flip[1] = -1.0f; + context.viewport_flip[2] = 1.0f; + context.viewport_flip[3] = 1.0f; glViewport(0, 0, display_w, display_h); glDepthRange(0, 1); } } -void sync_clipping(GLContext &context, const GxmContextState &state, const bool hardware_flip) { +void sync_clipping(GLContext &context, const GxmContextState &state) { const GLsizei display_h = state.color_surface.height; const GLsizei scissor_x = state.region_clip_min.x; GLsizei scissor_y = 0; - if (hardware_flip && context.viewport_flip[1] == -1.0f) + if (context.viewport_flip[1] == -1.0f) scissor_y = state.region_clip_min.y; else scissor_y = display_h - state.region_clip_max.y - 1; @@ -385,8 +381,8 @@ bool sync_state(GLContext &context, const GxmContextState &state, const MemState const GLFragmentProgram &fragment_program = *reinterpret_cast( gxm_fragment_program.renderer_data.get()); - sync_viewport(context, state, config.hardware_flip); - sync_clipping(context, state, config.hardware_flip); + sync_viewport(context, state); + sync_clipping(context, state); sync_cull(context, state); glEnable(GL_DEPTH_TEST); diff --git a/vita3k/renderer/src/scene.cpp b/vita3k/renderer/src/scene.cpp index d7202ba2..0f1fa4bb 100644 --- a/vita3k/renderer/src/scene.cpp +++ b/vita3k/renderer/src/scene.cpp @@ -65,7 +65,7 @@ COMMAND(handle_sync_surface_data) { switch (renderer.current_backend) { case Backend::OpenGL: { gl::get_surface_data(*reinterpret_cast(render_context), width, height, - stride_in_pixels, pixels, state->color_surface.colorFormat, !config.hardware_flip); + stride_in_pixels, pixels, state->color_surface.colorFormat); break; } diff --git a/vita3k/renderer/src/state_set.cpp b/vita3k/renderer/src/state_set.cpp index b4f270d1..b1d15dd6 100644 --- a/vita3k/renderer/src/state_set.cpp +++ b/vita3k/renderer/src/state_set.cpp @@ -28,7 +28,7 @@ COMMAND_SET_STATE(region_clip) { switch (renderer.current_backend) { case Backend::OpenGL: { - gl::sync_clipping(*reinterpret_cast(render_context), *state, config.hardware_flip); + gl::sync_clipping(*reinterpret_cast(render_context), *state); break; } @@ -134,7 +134,7 @@ COMMAND_SET_STATE(viewport) { // Sync switch (renderer.current_backend) { case Backend::OpenGL: { - gl::sync_viewport(*reinterpret_cast(render_context), *state, config.hardware_flip); + gl::sync_viewport(*reinterpret_cast(render_context), *state); break; } diff --git a/vita3k/shader/include/shader/usse_types.h b/vita3k/shader/include/shader/usse_types.h index a9997d22..c62ea1b8 100644 --- a/vita3k/shader/include/shader/usse_types.h +++ b/vita3k/shader/include/shader/usse_types.h @@ -358,13 +358,6 @@ struct UniformBuffer { bool rw; // TODO confirm this }; -struct UniformInputSource { - std::string name; - // resource index - uint32_t index; - bool in_mem; -}; - struct AttributeInputSource { std::string name; @@ -390,7 +383,7 @@ struct DependentSamplerInputSource { }; // Read source field in Input struct -using InputSource = std::variant; +using InputSource = std::variant; /** * Input parameters that are usually copied into PA or SA diff --git a/vita3k/shader/src/gxp_parser.cpp b/vita3k/shader/src/gxp_parser.cpp index d47a29e7..249c33b7 100644 --- a/vita3k/shader/src/gxp_parser.cpp +++ b/vita3k/shader/src/gxp_parser.cpp @@ -90,28 +90,25 @@ ProgramInput shader::get_program_input(const SceGxmProgram &program) { const auto [store_type, param_type_name] = shader::get_parameter_type_store_and_name(parameter_type); // Make the type - Input item; - item.type = store_type; - item.offset = offset; - item.component_count = parameter.component_count; - item.array_size = parameter.array_size; gxp::GenericParameterType param_type = gxp::parameter_generic_type(parameter); - item.generic_type = translate_generic_type(param_type); - item.bank = is_uniform ? RegisterBank::SECATTR : RegisterBank::PRIMATTR; if (!is_uniform) { + Input item; + item.type = store_type; + item.offset = offset; + item.component_count = parameter.component_count; + item.array_size = parameter.array_size; + + item.generic_type = translate_generic_type(param_type); + item.bank = RegisterBank::PRIMATTR; + AttributeInputSource source; source.name = var_name; source.index = parameter.resource_index; source.semantic = parameter.semantic; item.source = source; + program_input.inputs.push_back(item); } else { - UniformInputSource source; - source.name = var_name; - source.index = parameter.resource_index; - const uint32_t reg_block_size = container ? container->size_in_f32 : 0; - source.in_mem = parameter.resource_index > reg_block_size; - item.source = source; uint32_t vector_size = parameter.component_count * get_data_type_size(store_type); if (parameter.array_size != 1) { if (is_float_data_type(store_type) && parameter.component_count != 1) { @@ -123,6 +120,8 @@ ProgramInput shader::get_program_input(const SceGxmProgram &program) { const uint32_t parameter_size = parameter.array_size * vector_size; const uint32_t parameter_size_in_f32 = (parameter_size + 3) / 4; if (uniform_buffers.find(parameter.container_index) == uniform_buffers.end()) { + const std::uint32_t reg_block_size = container ? container->size_in_f32 : 0; + UniformBuffer buffer; buffer.index = (parameter.container_index + 1) % SCE_GXM_REAL_MAX_UNIFORM_BUFFER; buffer.reg_block_size = reg_block_size; @@ -136,8 +135,6 @@ ProgramInput shader::get_program_input(const SceGxmProgram &program) { buffer.reg_start_offset = std::min(buffer.reg_start_offset, static_cast(offset)); } } - - program_input.inputs.push_back(item); break; } diff --git a/vita3k/shader/src/spirv_recompiler.cpp b/vita3k/shader/src/spirv_recompiler.cpp index f45d0585..edc61dbc 100644 --- a/vita3k/shader/src/spirv_recompiler.cpp +++ b/vita3k/shader/src/spirv_recompiler.cpp @@ -741,13 +741,11 @@ static SpirvShaderParameters create_parameters(spv::Builder &b, const SceGxmProg uniform_buffers.emplace(buffer.index, block); } - if (features.use_ubo) { - for (const auto buffer : program_input.uniform_buffers) { - if (buffer.reg_block_size > 0) { - const uint32_t reg_block_size_in_f32v = (buffer.reg_block_size + 3) / 4; - const auto spv_buffer = uniform_buffers.at(buffer.index); - copy_uniform_block_to_register(b, spv_params.uniforms, spv_buffer, ite_copy, buffer.reg_start_offset / 4, reg_block_size_in_f32v); - } + for (const auto buffer : program_input.uniform_buffers) { + if (buffer.reg_block_size > 0) { + const uint32_t reg_block_size_in_f32v = (buffer.reg_block_size + 3) / 4; + const auto spv_buffer = uniform_buffers.at(buffer.index); + copy_uniform_block_to_register(b, spv_params.uniforms, spv_buffer, ite_copy, buffer.reg_start_offset / 4, reg_block_size_in_f32v); } } @@ -849,12 +847,6 @@ static SpirvShaderParameters create_parameters(spv::Builder &b, const SceGxmProg // Pair sort automatically sort offset for us std::sort(literal_pairs.begin(), literal_pairs.end()); }, - [&](const UniformInputSource &s) { - // In ubo mode we copy using default uniform buffer - if (!features.use_ubo) { - add_var_to_reg(input, s.name, 0, false, -1); - } - }, [&](const UniformBufferInputSource &s) { Operand reg; reg.bank = RegisterBank::SECATTR; @@ -928,7 +920,7 @@ static SpirvShaderParameters create_parameters(spv::Builder &b, const SceGxmProg translation_state.screen_height_id = height_id; } - if (program_type == SceGxmProgramType::Vertex && features.hardware_flip) { + if (program_type == SceGxmProgramType::Vertex) { // Create variable that helps us do flipping // TODO: Not emit this on Vulkan or DirectX spv::Id f32 = b.makeFloatType(32); @@ -1486,7 +1478,6 @@ void convert_gxp_to_glsl_from_filepath(const std::string &shader_filepath) { features.direct_fragcolor = false; features.support_shader_interlock = true; features.pack_unpack_half_through_ext = false; - features.use_ubo = true; convert_gxp_to_glsl(*gxp_program, shader_filepath_str.filename().string(), features, false, true);