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
parent f5366c91a7
commit 568af756cc
3 changed files with 75 additions and 35 deletions

View File

@ -1830,8 +1830,8 @@ namespace rsx
return {};
}
template <typename surface_store_type>
bool test_if_descriptor_expired(commandbuffer_type& cmd, surface_store_type& surface_cache, sampled_image_descriptor* descriptor)
template <typename surface_store_type, typename RsxTextureType>
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);
if (result.second && descriptor->is_cyclic_reference)
@ -1849,9 +1849,41 @@ namespace rsx
}
else if (descriptor->image_handle)
{
descriptor->external_subresource_desc.external_handle = descriptor->image_handle->image();
descriptor->external_subresource_desc.op = deferred_request_command::copy_image_dynamic;
// Rebuild duplicate surface
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->image_handle = nullptr;
}
else
{
@ -1864,7 +1896,7 @@ namespace rsx
}
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++;

View File

@ -285,14 +285,16 @@ void GLGSRender::load_texture_env()
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());
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])
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
{
@ -312,14 +314,16 @@ void GLGSRender::load_texture_env()
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());
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())
{
*sampler_state = m_gl_texture_cache.upload_texture(cmd, rsx::method_registers.vertex_textures[i], m_rtts);
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
*sampler_state = {};

View File

@ -146,9 +146,9 @@ void VKGSRender::load_texture_env()
{
// Load textures
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;
return true;
@ -168,12 +168,14 @@ void VKGSRender::load_texture_env()
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());
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);
*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)
{
@ -186,21 +188,21 @@ void VKGSRender::load_texture_env()
f32 min_lod = 0.f, max_lod = 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;
VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER;
if (texture_format >= CELL_GCM_TEXTURE_DEPTH24_D8 && texture_format <= CELL_GCM_TEXTURE_DEPTH16_FLOAT)
{
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 auto wrap_s = vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_s());
const auto wrap_t = vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_t());
const auto wrap_r = vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_r());
const auto border_color = vk::get_border_color(rsx::method_registers.fragment_textures[i].border_color());
const f32 af_level = vk::max_aniso(tex.max_aniso());
const auto wrap_s = vk::vk_wrap_mode(tex.wrap_s());
const auto wrap_t = vk::vk_wrap_mode(tex.wrap_t());
const auto wrap_r = vk::vk_wrap_mode(tex.wrap_r());
const auto border_color = vk::get_border_color(tex.border_color());
// Check if non-point filtering can even be used on this format
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;
}
const auto mipmap_count = rsx::method_registers.fragment_textures[i].get_exact_mipmap_count();
min_filter = vk::get_min_filter(rsx::method_registers.fragment_textures[i].min_filter());
const auto mipmap_count = tex.get_exact_mipmap_count();
min_filter = vk::get_min_filter(tex.min_filter());
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
{
@ -250,9 +252,9 @@ void VKGSRender::load_texture_env()
if (actual_mipmaps > 1.f)
{
min_lod = rsx::method_registers.fragment_textures[i].min_lod();
max_lod = rsx::method_registers.fragment_textures[i].max_lod();
lod_bias = rsx::method_registers.fragment_textures[i].bias();
min_lod = tex.min_lod();
max_lod = tex.max_lod();
lod_bias = tex.bias();
min_lod = std::min(min_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>();
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())
{
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)
{
@ -317,10 +321,10 @@ void VKGSRender::load_texture_env()
}
bool replace = !vs_sampler_handles[i];
const VkBool32 unnormalized_coords = !!(rsx::method_registers.vertex_textures[i].format() & CELL_GCM_TEXTURE_UN);
const auto min_lod = rsx::method_registers.vertex_textures[i].min_lod();
const auto max_lod = rsx::method_registers.vertex_textures[i].max_lod();
const auto border_color = vk::get_border_color(rsx::method_registers.vertex_textures[i].border_color());
const VkBool32 unnormalized_coords = !!(tex.format() & CELL_GCM_TEXTURE_UN);
const auto min_lod = tex.min_lod();
const auto max_lod = tex.max_lod();
const auto border_color = vk::get_border_color(tex.border_color());
if (vs_sampler_handles[i])
{