diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index a3cdd06986..3dcac04f09 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -694,6 +694,7 @@ void GLGSRender::begin() if (m_graphics_state & rsx::pipeline_state::invalidate_pipeline_bits) { // Shaders need to be reloaded. + m_prev_program = m_program; m_program = nullptr; } } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index c37228afe9..8d6c6010d9 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -767,7 +767,6 @@ bool GLGSRender::load_program() } } - const bool was_interpreter = m_shader_interpreter.is_interpreter(m_program); m_vertex_prog = nullptr; m_fragment_prog = nullptr; @@ -796,15 +795,32 @@ bool GLGSRender::load_program() m_program = nullptr; } - if (!m_program && (shadermode == shader_mode::async_with_interpreter || shadermode == shader_mode::interpreter_only)) + if (shadermode == shader_mode::async_with_interpreter || shadermode == shader_mode::interpreter_only) { - // Fall back to interpreter - m_program = m_shader_interpreter.get(current_fp_metadata); - if (was_interpreter != m_shader_interpreter.is_interpreter(m_program)) + const bool is_interpreter = !m_program; + const bool was_interpreter = m_shader_interpreter.is_interpreter(m_prev_program); + + // First load the next program if not available + if (!m_program) { + m_program = m_shader_interpreter.get(current_fp_metadata); + // Program has changed, reupload m_interpreter_state = rsx::invalidate_pipeline_bits; } + + // If swapping between interpreter and recompiler, we need to adjust some flags to reupload data as needed. + if (is_interpreter != was_interpreter) + { + // Always reupload transform constants when going between interpreter and recompiler + m_graphics_state |= rsx::transform_constants_dirty; + + // Always reload fragment constansts when moving from interpreter back to recompiler. + if (was_interpreter) + { + m_graphics_state |= rsx::fragment_constants_dirty; + } + } } return m_program != nullptr; @@ -989,6 +1005,11 @@ void GLGSRender::load_program_env() handled_flags |= rsx::pipeline_state::fragment_constants_dirty; } + if (m_shader_interpreter.is_interpreter(m_program)) + { + ensure(m_transform_constants_buffer->bound_range().second >= 468 * 16); + } + m_graphics_state.clear(handled_flags); } @@ -999,7 +1020,9 @@ bool GLGSRender::is_current_program_interpreted() const void GLGSRender::upload_transform_constants(const rsx::io_buffer& buffer) { - const usz transform_constants_size = (!m_vertex_prog || m_vertex_prog->has_indexed_constants) ? 8192 : m_vertex_prog->constant_ids.size() * 16; + const bool is_interpreter = m_shader_interpreter.is_interpreter(m_program); + const usz transform_constants_size = (is_interpreter || m_vertex_prog->has_indexed_constants) ? 8192 : m_vertex_prog->constant_ids.size() * 16; + if (transform_constants_size) { const auto constant_ids = (transform_constants_size == 8192) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 01579a445b..d28898c052 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -78,6 +78,7 @@ class GLGSRender : public GSRender, public ::rsx::reports::ZCULL_control gl::sampler_state m_vs_sampler_states[rsx::limits::vertex_textures_count]; // Vertex textures gl::glsl::program *m_program = nullptr; + gl::glsl::program* m_prev_program = nullptr; const GLFragmentProgram *m_fragment_prog = nullptr; const GLVertexProgram *m_vertex_prog = nullptr; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 4490ff54bf..573f837707 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1982,14 +1982,32 @@ bool VKGSRender::load_program() m_program = nullptr; } - if (!m_program && (shadermode == shader_mode::async_with_interpreter || shadermode == shader_mode::interpreter_only)) + if (shadermode == shader_mode::async_with_interpreter || shadermode == shader_mode::interpreter_only) { - if (!m_shader_interpreter.is_interpreter(m_prev_program)) + const bool is_interpreter = !m_program; + const bool was_interpreter = m_shader_interpreter.is_interpreter(m_prev_program); + + // First load the next program if not available + if (!m_program) { + m_program = m_shader_interpreter.get(m_pipeline_properties, current_fp_metadata); + + // Program has changed, reupload m_interpreter_state = rsx::invalidate_pipeline_bits; } - m_program = m_shader_interpreter.get(m_pipeline_properties, current_fp_metadata); + // If swapping between interpreter and recompiler, we need to adjust some flags to reupload data as needed. + if (is_interpreter != was_interpreter) + { + // Always reupload transform constants when going between interpreter and recompiler + m_graphics_state |= rsx::transform_constants_dirty; + + // Always reload fragment constansts when moving from interpreter back to recompiler. + if (was_interpreter) + { + m_graphics_state |= rsx::fragment_constants_dirty; + } + } } return m_program != nullptr; @@ -2051,7 +2069,8 @@ void VKGSRender::load_program_env() return std::make_pair(m_instancing_buffer_ring_info.map(constants_data_table_offset, size), size); }); - m_draw_processor.fill_constants_instancing_buffer(indirection_table_buf, constants_array_buf, m_vertex_prog); + const auto bound_vertex_prog = m_shader_interpreter.is_interpreter(m_program) ? nullptr : m_vertex_prog; + m_draw_processor.fill_constants_instancing_buffer(indirection_table_buf, constants_array_buf, bound_vertex_prog); m_instancing_buffer_ring_info.unmap(); m_instancing_indirection_buffer_info = { m_instancing_buffer_ring_info.heap->value, indirection_table_offset, indirection_table_buf.size() }; @@ -2224,6 +2243,11 @@ void VKGSRender::load_program_env() handled_flags |= rsx::pipeline_state::fragment_constants_dirty; } + if (m_shader_interpreter.is_interpreter(m_program)) + { + ensure(m_vertex_constants_buffer_info.range >= 468 * 16); + } + m_graphics_state.clear(handled_flags); } @@ -2234,7 +2258,9 @@ bool VKGSRender::is_current_program_interpreted() const void VKGSRender::upload_transform_constants(const rsx::io_buffer& buffer) { - const usz transform_constants_size = (!m_vertex_prog || m_vertex_prog->has_indexed_constants) ? 8192 : m_vertex_prog->constant_ids.size() * 16; + const bool is_interpreter = m_shader_interpreter.is_interpreter(m_program); + const usz transform_constants_size = (is_interpreter || m_vertex_prog->has_indexed_constants) ? 8192 : m_vertex_prog->constant_ids.size() * 16; + if (transform_constants_size) { check_heap_status(VK_HEAP_CHECK_TRANSFORM_CONSTANTS_STORAGE);