mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 21:41:26 +12: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
7965a0313c
commit
e1c6df0df3
5 changed files with 49 additions and 7 deletions
|
@ -790,7 +790,7 @@ namespace rsx
|
||||||
|
|
||||||
const int translated_offset = full_reupload
|
const int translated_offset = full_reupload
|
||||||
? instance_config.patch_load_offset
|
? 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)
|
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)
|
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
|
// Shouldn't be reachable, but handle it correctly anyway
|
||||||
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_vertex_prog->overlaps_constants_range(index, count))
|
||||||
|
{
|
||||||
|
// Nothing meaningful to us
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<u32, u32> data_range {};
|
std::pair<u32, u32> data_range {};
|
||||||
void* data_source = nullptr;
|
void* data_source = nullptr;
|
||||||
const auto bound_range = m_transform_constants_buffer->bound_range();
|
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_range = { bound_range.first + byte_offset, byte_count};
|
||||||
data_source = ®S(ctx)->transform_constants[index];
|
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 write_offset = xform_id * 16;
|
||||||
const auto byte_count = count * 16;
|
const auto byte_count = count * 16;
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace rsx
|
||||||
multisampled_textures == other.multisampled_textures;
|
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
|
// The constant ids should be sorted, so just find the first one and check for continuity
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
@ -157,4 +157,31 @@ namespace rsx
|
||||||
// OOB or partial match
|
// OOB or partial match
|
||||||
return -1;
|
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.
|
// 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
|
// 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
|
// 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)
|
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
|
// Shouldn't be reachable, but handle it correctly anyway
|
||||||
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_vertex_prog->overlaps_constants_range(index, count))
|
||||||
|
{
|
||||||
|
// Nothing meaningful to us
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Hot-patching transform constants mid-draw (instanced draw)
|
// Hot-patching transform constants mid-draw (instanced draw)
|
||||||
std::pair<VkDeviceSize, VkDeviceSize> data_range;
|
std::pair<VkDeviceSize, VkDeviceSize> data_range;
|
||||||
void* data_source = nullptr;
|
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_range = { m_vertex_constants_buffer_info.offset + byte_offset, byte_count };
|
||||||
data_source = ®S(ctx)->transform_constants[index];
|
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 write_offset = xform_id * 16;
|
||||||
const auto byte_count = count * 16;
|
const auto byte_count = count * 16;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue