diff --git a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp index 7be332fc60..389efe0a2e 100644 --- a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp +++ b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp @@ -790,7 +790,7 @@ namespace rsx const int translated_offset = full_reupload ? instance_config.patch_load_offset - : prog->TranslateConstantsRange(instance_config.patch_load_offset, instance_config.patch_load_count); + : prog->translate_constants_range(instance_config.patch_load_offset, instance_config.patch_load_count); if (translated_offset >= 0) { diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 34f0380ad3..c37228afe9 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1045,13 +1045,19 @@ void GLGSRender::update_vertex_env(const gl::vertex_upload_info& upload_info) void GLGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 count) { - if (!m_vertex_prog) + if (!m_program || !m_vertex_prog) { // Shouldn't be reachable, but handle it correctly anyway m_graphics_state |= rsx::pipeline_state::transform_constants_dirty; return; } + if (!m_vertex_prog->overlaps_constants_range(index, count)) + { + // Nothing meaningful to us + return; + } + std::pair data_range {}; void* data_source = nullptr; const auto bound_range = m_transform_constants_buffer->bound_range(); @@ -1065,7 +1071,7 @@ void GLGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 cou data_range = { bound_range.first + byte_offset, byte_count}; data_source = ®S(ctx)->transform_constants[index]; } - else if (auto xform_id = m_vertex_prog->TranslateConstantsRange(index, count); xform_id >= 0) + else if (auto xform_id = m_vertex_prog->translate_constants_range(index, count); xform_id >= 0) { const auto write_offset = xform_id * 16; const auto byte_count = count * 16; diff --git a/rpcs3/Emu/RSX/Program/program_util.cpp b/rpcs3/Emu/RSX/Program/program_util.cpp index 9f44f05505..e5daf319fc 100644 --- a/rpcs3/Emu/RSX/Program/program_util.cpp +++ b/rpcs3/Emu/RSX/Program/program_util.cpp @@ -110,7 +110,7 @@ namespace rsx multisampled_textures == other.multisampled_textures; } - int VertexProgramBase::TranslateConstantsRange(int first_index, int count) const + int VertexProgramBase::translate_constants_range(int first_index, int count) const { // The constant ids should be sorted, so just find the first one and check for continuity int index = -1; @@ -157,4 +157,31 @@ namespace rsx // OOB or partial match return -1; } + + bool VertexProgramBase::overlaps_constants_range(int first_index, int count) const + { + if (has_indexed_constants) + { + return true; + } + + const int last_index = first_index + count - 1; + + // Early rejection test + if (constant_ids.empty() || first_index > constant_ids.back() || last_index < first_index) + { + return false; + } + + // Check for any hits + for (auto& idx : constant_ids) + { + if (idx >= first_index && idx <= last_index) + { + return true; + } + } + + return false; + } } diff --git a/rpcs3/Emu/RSX/Program/program_util.h b/rpcs3/Emu/RSX/Program/program_util.h index c8011a3db2..8159b27845 100644 --- a/rpcs3/Emu/RSX/Program/program_util.h +++ b/rpcs3/Emu/RSX/Program/program_util.h @@ -67,6 +67,9 @@ namespace rsx // Translates an incoming range of constants against our mapping. // If there is no linear mapping available, return -1, otherwise returns the translated index of the first slot // TODO: Move this somewhere else during refactor - int TranslateConstantsRange(int first_index, int count) const; + int translate_constants_range(int first_index, int count) const; + + // Returns true if this program consumes any constants in the range [first, first + count - 1] + bool overlaps_constants_range(int first_index, int count) const; }; } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index ea3d83cdf3..8ebb41c099 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2443,13 +2443,19 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_ void VKGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 count) { - if (!m_vertex_prog) + if (!m_program || !m_vertex_prog) { // Shouldn't be reachable, but handle it correctly anyway m_graphics_state |= rsx::pipeline_state::transform_constants_dirty; return; } + if (!m_vertex_prog->overlaps_constants_range(index, count)) + { + // Nothing meaningful to us + return; + } + // Hot-patching transform constants mid-draw (instanced draw) std::pair data_range; void* data_source = nullptr; @@ -2463,7 +2469,7 @@ void VKGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 cou data_range = { m_vertex_constants_buffer_info.offset + byte_offset, byte_count }; data_source = ®S(ctx)->transform_constants[index]; } - else if (auto xform_id = m_vertex_prog->TranslateConstantsRange(index, count); xform_id >= 0) + else if (auto xform_id = m_vertex_prog->translate_constants_range(index, count); xform_id >= 0) { const auto write_offset = xform_id * 16; const auto byte_count = count * 16;