mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
rsx: Fix dynamic constants patching when draw call is skipped
- Also adds an optimization to skip reuploads when patch occurs outside our critical range.
This commit is contained in:
parent
912388cc6a
commit
58b55d7576
5 changed files with 49 additions and 7 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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<u32, u32> 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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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<VkDeviceSize, VkDeviceSize> 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;
|
||||
|
|
Loading…
Add table
Reference in a new issue