rsx: Fix expired sampler descriptors

- Rebuilding when strict mode is enabled was incomplete.
  The copy has to be redone if the source has been updated.
This commit is contained in:
kd-11 2021-06-05 20:05:12 +03:00 committed by kd-11
commit 568af756cc
3 changed files with 75 additions and 35 deletions

View file

@ -1830,8 +1830,8 @@ namespace rsx
return {}; return {};
} }
template <typename surface_store_type> template <typename surface_store_type, typename RsxTextureType>
bool test_if_descriptor_expired(commandbuffer_type& cmd, surface_store_type& surface_cache, sampled_image_descriptor* descriptor) bool test_if_descriptor_expired(commandbuffer_type& cmd, surface_store_type& surface_cache, sampled_image_descriptor* descriptor, const RsxTextureType& tex)
{ {
auto result = descriptor->is_expired(surface_cache); auto result = descriptor->is_expired(surface_cache);
if (result.second && descriptor->is_cyclic_reference) if (result.second && descriptor->is_cyclic_reference)
@ -1849,9 +1849,41 @@ namespace rsx
} }
else if (descriptor->image_handle) else if (descriptor->image_handle)
{ {
descriptor->external_subresource_desc.external_handle = descriptor->image_handle->image(); // Rebuild duplicate surface
descriptor->external_subresource_desc.op = deferred_request_command::copy_image_dynamic; auto src = descriptor->image_handle->image();
rsx::image_section_attributes_t attr;
attr.address = descriptor->ref_address;
attr.gcm_format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
attr.width = src->width();
attr.height = src->height();
attr.depth = 1;
attr.mipmaps = 1;
attr.pitch = 0; // Unused
attr.slice_h = src->height();
attr.bpp = get_format_block_size_in_bytes(attr.gcm_format);
attr.swizzled = false;
// Sanity checks
const bool gcm_format_is_depth = helpers::is_gcm_depth_format(attr.gcm_format);
const bool bound_surface_is_depth = surface_cache.m_bound_depth_stencil.first == attr.address;
if (!gcm_format_is_depth && bound_surface_is_depth)
{
// While the copy routines can perform a typeless cast, prefer to not cross the aspect barrier if possible
// This avoids messing with other solutions such as texture redirection as well
attr.gcm_format = helpers::get_compatible_depth_format(attr.gcm_format);
}
descriptor->external_subresource_desc =
{
src,
rsx::deferred_request_command::copy_image_dynamic,
attr,
{},
rsx::default_remap_vector
};
descriptor->external_subresource_desc.do_not_cache = true; descriptor->external_subresource_desc.do_not_cache = true;
descriptor->image_handle = nullptr;
} }
else else
{ {
@ -1864,7 +1896,7 @@ namespace rsx
} }
template <typename RsxTextureType, typename surface_store_type, typename ...Args> template <typename RsxTextureType, typename surface_store_type, typename ...Args>
sampled_image_descriptor upload_texture(commandbuffer_type& cmd, RsxTextureType& tex, surface_store_type& m_rtts, Args&&... extras) sampled_image_descriptor upload_texture(commandbuffer_type& cmd, const RsxTextureType& tex, surface_store_type& m_rtts, Args&&... extras)
{ {
m_texture_upload_calls_this_frame++; m_texture_upload_calls_this_frame++;

View file

@ -285,14 +285,16 @@ void GLGSRender::load_texture_env()
fs_sampler_state[i] = std::make_unique<gl::texture_cache::sampled_image_descriptor>(); fs_sampler_state[i] = std::make_unique<gl::texture_cache::sampled_image_descriptor>();
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get()); auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
if (m_samplers_dirty || m_textures_dirty[i] || m_gl_texture_cache.test_if_descriptor_expired(cmd, m_rtts, sampler_state)) const auto& tex = rsx::method_registers.fragment_textures[i];
if (m_samplers_dirty || m_textures_dirty[i] || m_gl_texture_cache.test_if_descriptor_expired(cmd, m_rtts, sampler_state, tex))
{ {
if (rsx::method_registers.fragment_textures[i].enabled()) if (tex.enabled())
{ {
*sampler_state = m_gl_texture_cache.upload_texture(cmd, rsx::method_registers.fragment_textures[i], m_rtts); *sampler_state = m_gl_texture_cache.upload_texture(cmd, tex, m_rtts);
if (m_textures_dirty[i]) if (m_textures_dirty[i])
m_fs_sampler_states[i].apply(rsx::method_registers.fragment_textures[i], fs_sampler_state[i].get()); m_fs_sampler_states[i].apply(tex, fs_sampler_state[i].get());
} }
else else
{ {
@ -312,14 +314,16 @@ void GLGSRender::load_texture_env()
vs_sampler_state[i] = std::make_unique<gl::texture_cache::sampled_image_descriptor>(); vs_sampler_state[i] = std::make_unique<gl::texture_cache::sampled_image_descriptor>();
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get()); auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
if (m_samplers_dirty || m_vertex_textures_dirty[i] || m_gl_texture_cache.test_if_descriptor_expired(cmd, m_rtts, sampler_state)) const auto& tex = rsx::method_registers.vertex_textures[i];
if (m_samplers_dirty || m_vertex_textures_dirty[i] || m_gl_texture_cache.test_if_descriptor_expired(cmd, m_rtts, sampler_state, tex))
{ {
if (rsx::method_registers.vertex_textures[i].enabled()) if (rsx::method_registers.vertex_textures[i].enabled())
{ {
*sampler_state = m_gl_texture_cache.upload_texture(cmd, rsx::method_registers.vertex_textures[i], m_rtts); *sampler_state = m_gl_texture_cache.upload_texture(cmd, rsx::method_registers.vertex_textures[i], m_rtts);
if (m_vertex_textures_dirty[i]) if (m_vertex_textures_dirty[i])
m_vs_sampler_states[i].apply(rsx::method_registers.vertex_textures[i], vs_sampler_state[i].get()); m_vs_sampler_states[i].apply(tex, vs_sampler_state[i].get());
} }
else else
*sampler_state = {}; *sampler_state = {};

View file

@ -146,9 +146,9 @@ void VKGSRender::load_texture_env()
{ {
// Load textures // Load textures
bool check_for_cyclic_refs = false; bool check_for_cyclic_refs = false;
auto check_surface_cache_sampler = [&](auto descriptor) auto check_surface_cache_sampler = [&](auto descriptor, const auto& tex)
{ {
if (!m_texture_cache.test_if_descriptor_expired(*m_current_command_buffer, m_rtts, descriptor)) if (!m_texture_cache.test_if_descriptor_expired(*m_current_command_buffer, m_rtts, descriptor, tex))
{ {
check_for_cyclic_refs |= descriptor->is_cyclic_reference; check_for_cyclic_refs |= descriptor->is_cyclic_reference;
return true; return true;
@ -168,12 +168,14 @@ void VKGSRender::load_texture_env()
fs_sampler_state[i] = std::make_unique<vk::texture_cache::sampled_image_descriptor>(); fs_sampler_state[i] = std::make_unique<vk::texture_cache::sampled_image_descriptor>();
auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get()); auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
if (m_samplers_dirty || m_textures_dirty[i] || !check_surface_cache_sampler(sampler_state)) const auto& tex = rsx::method_registers.fragment_textures[i];
if (m_samplers_dirty || m_textures_dirty[i] || !check_surface_cache_sampler(sampler_state, tex))
{ {
if (rsx::method_registers.fragment_textures[i].enabled()) if (tex.enabled())
{ {
check_heap_status(VK_HEAP_CHECK_TEXTURE_UPLOAD_STORAGE); check_heap_status(VK_HEAP_CHECK_TEXTURE_UPLOAD_STORAGE);
*sampler_state = m_texture_cache.upload_texture(*m_current_command_buffer, rsx::method_registers.fragment_textures[i], m_rtts); *sampler_state = m_texture_cache.upload_texture(*m_current_command_buffer, tex, m_rtts);
if (sampler_state->is_cyclic_reference) if (sampler_state->is_cyclic_reference)
{ {
@ -186,21 +188,21 @@ void VKGSRender::load_texture_env()
f32 min_lod = 0.f, max_lod = 0.f; f32 min_lod = 0.f, max_lod = 0.f;
f32 lod_bias = 0.f; f32 lod_bias = 0.f;
const u32 texture_format = rsx::method_registers.fragment_textures[i].format() & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN); const u32 texture_format = tex.format() & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN);
VkBool32 compare_enabled = VK_FALSE; VkBool32 compare_enabled = VK_FALSE;
VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER; VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER;
if (texture_format >= CELL_GCM_TEXTURE_DEPTH24_D8 && texture_format <= CELL_GCM_TEXTURE_DEPTH16_FLOAT) if (texture_format >= CELL_GCM_TEXTURE_DEPTH24_D8 && texture_format <= CELL_GCM_TEXTURE_DEPTH16_FLOAT)
{ {
compare_enabled = VK_TRUE; compare_enabled = VK_TRUE;
depth_compare_mode = vk::get_compare_func(rsx::method_registers.fragment_textures[i].zfunc(), true); depth_compare_mode = vk::get_compare_func(tex.zfunc(), true);
} }
const f32 af_level = vk::max_aniso(rsx::method_registers.fragment_textures[i].max_aniso()); const f32 af_level = vk::max_aniso(tex.max_aniso());
const auto wrap_s = vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_s()); const auto wrap_s = vk::vk_wrap_mode(tex.wrap_s());
const auto wrap_t = vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_t()); const auto wrap_t = vk::vk_wrap_mode(tex.wrap_t());
const auto wrap_r = vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_r()); const auto wrap_r = vk::vk_wrap_mode(tex.wrap_r());
const auto border_color = vk::get_border_color(rsx::method_registers.fragment_textures[i].border_color()); const auto border_color = vk::get_border_color(tex.border_color());
// Check if non-point filtering can even be used on this format // Check if non-point filtering can even be used on this format
bool can_sample_linear; bool can_sample_linear;
@ -218,12 +220,12 @@ void VKGSRender::load_texture_env()
can_sample_linear = m_device->get_format_properties(vk_format).optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; can_sample_linear = m_device->get_format_properties(vk_format).optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
} }
const auto mipmap_count = rsx::method_registers.fragment_textures[i].get_exact_mipmap_count(); const auto mipmap_count = tex.get_exact_mipmap_count();
min_filter = vk::get_min_filter(rsx::method_registers.fragment_textures[i].min_filter()); min_filter = vk::get_min_filter(tex.min_filter());
if (can_sample_linear) if (can_sample_linear)
{ {
mag_filter = vk::get_mag_filter(rsx::method_registers.fragment_textures[i].mag_filter()); mag_filter = vk::get_mag_filter(tex.mag_filter());
} }
else else
{ {
@ -250,9 +252,9 @@ void VKGSRender::load_texture_env()
if (actual_mipmaps > 1.f) if (actual_mipmaps > 1.f)
{ {
min_lod = rsx::method_registers.fragment_textures[i].min_lod(); min_lod = tex.min_lod();
max_lod = rsx::method_registers.fragment_textures[i].max_lod(); max_lod = tex.max_lod();
lod_bias = rsx::method_registers.fragment_textures[i].bias(); lod_bias = tex.bias();
min_lod = std::min(min_lod, actual_mipmaps - 1.f); min_lod = std::min(min_lod, actual_mipmaps - 1.f);
max_lod = std::min(max_lod, actual_mipmaps - 1.f); max_lod = std::min(max_lod, actual_mipmaps - 1.f);
@ -304,12 +306,14 @@ void VKGSRender::load_texture_env()
vs_sampler_state[i] = std::make_unique<vk::texture_cache::sampled_image_descriptor>(); vs_sampler_state[i] = std::make_unique<vk::texture_cache::sampled_image_descriptor>();
auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get()); auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
if (m_samplers_dirty || m_vertex_textures_dirty[i] || !check_surface_cache_sampler(sampler_state)) const auto& tex = rsx::method_registers.vertex_textures[i];
if (m_samplers_dirty || m_vertex_textures_dirty[i] || !check_surface_cache_sampler(sampler_state, tex))
{ {
if (rsx::method_registers.vertex_textures[i].enabled()) if (rsx::method_registers.vertex_textures[i].enabled())
{ {
check_heap_status(VK_HEAP_CHECK_TEXTURE_UPLOAD_STORAGE); check_heap_status(VK_HEAP_CHECK_TEXTURE_UPLOAD_STORAGE);
*sampler_state = m_texture_cache.upload_texture(*m_current_command_buffer, rsx::method_registers.vertex_textures[i], m_rtts); *sampler_state = m_texture_cache.upload_texture(*m_current_command_buffer, tex, m_rtts);
if (sampler_state->is_cyclic_reference || sampler_state->external_subresource_desc.do_not_cache) if (sampler_state->is_cyclic_reference || sampler_state->external_subresource_desc.do_not_cache)
{ {
@ -317,10 +321,10 @@ void VKGSRender::load_texture_env()
} }
bool replace = !vs_sampler_handles[i]; bool replace = !vs_sampler_handles[i];
const VkBool32 unnormalized_coords = !!(rsx::method_registers.vertex_textures[i].format() & CELL_GCM_TEXTURE_UN); const VkBool32 unnormalized_coords = !!(tex.format() & CELL_GCM_TEXTURE_UN);
const auto min_lod = rsx::method_registers.vertex_textures[i].min_lod(); const auto min_lod = tex.min_lod();
const auto max_lod = rsx::method_registers.vertex_textures[i].max_lod(); const auto max_lod = tex.max_lod();
const auto border_color = vk::get_border_color(rsx::method_registers.vertex_textures[i].border_color()); const auto border_color = vk::get_border_color(tex.border_color());
if (vs_sampler_handles[i]) if (vs_sampler_handles[i])
{ {