mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
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:
parent
f5366c91a7
commit
568af756cc
3 changed files with 75 additions and 35 deletions
|
@ -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++;
|
||||
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
|
@ -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])
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue