rsx: More fixes

- Tag surface store to help determine when contents have been invalidated
- Crop framebuffer textures if they are not the requested dimensions!
This commit is contained in:
kd-11 2017-10-31 18:45:54 +03:00
parent 963a87fed5
commit ec3e5c547f
7 changed files with 100 additions and 27 deletions

View File

@ -17,6 +17,7 @@ namespace rsx
struct surface_subresource_storage
{
surface_type surface = nullptr;
u32 base_address = 0;
u16 x = 0;
u16 y = 0;
@ -29,8 +30,8 @@ namespace rsx
surface_subresource_storage() {}
surface_subresource_storage(surface_type src, u16 X, u16 Y, u16 W, u16 H, bool _Bound, bool _Depth, bool _Clipped = false)
: surface(src), x(X), y(Y), w(W), h(H), is_bound(_Bound), is_depth_surface(_Depth), is_clipped(_Clipped)
surface_subresource_storage(u32 addr, surface_type src, u16 X, u16 Y, u16 W, u16 H, bool _Bound, bool _Depth, bool _Clipped = false)
: base_address(addr), surface(src), x(X), y(Y), w(W), h(H), is_bound(_Bound), is_depth_surface(_Depth), is_clipped(_Clipped)
{}
};
@ -114,6 +115,7 @@ namespace rsx
std::tuple<u32, surface_type> m_bound_depth_stencil = {};
std::list<surface_storage_type> invalidated_resources;
u64 cache_tag = 0ull;
surface_store() = default;
~surface_store() = default;
@ -272,6 +274,8 @@ namespace rsx
// u32 clip_x = clip_horizontal_reg;
// u32 clip_y = clip_vertical_reg;
cache_tag++;
// Make previous RTTs sampleable
for (std::tuple<u32, surface_type> &rtt : m_bound_render_targets)
{
@ -496,6 +500,8 @@ namespace rsx
{
invalidated_resources.push_back(std::move(It->second));
m_render_targets_storage.erase(It);
cache_tag++;
return;
}
}
@ -511,6 +517,8 @@ namespace rsx
{
invalidated_resources.push_back(std::move(It->second));
m_depth_stencil_storage.erase(It);
cache_tag++;
return;
}
}
@ -535,6 +543,9 @@ namespace rsx
{
invalidated_resources.push_back(std::move(It->second));
m_render_targets_storage.erase(It);
cache_tag++;
return;
}
}
else
@ -544,6 +555,9 @@ namespace rsx
{
invalidated_resources.push_back(std::move(It->second));
m_depth_stencil_storage.erase(It);
cache_tag++;
return;
}
}
}
@ -725,11 +739,11 @@ namespace rsx
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
continue;
else
return{ surface, 0, 0, 0, 0, false, false, false };
return{ this_address, surface, 0, 0, 0, 0, false, false, false };
}
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
return{ surface, x_offset, y_offset, w, h, address_is_bound(this_address, false), false, clipped };
return{ this_address, surface, x_offset, y_offset, w, h, address_is_bound(this_address, false), false, clipped };
}
}
@ -751,11 +765,11 @@ namespace rsx
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
continue;
else
return{ surface, 0, 0, 0, 0, false, true, false };
return{ this_address, surface, 0, 0, 0, 0, false, true, false };
}
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
return{ surface, x_offset, y_offset, w, h, address_is_bound(this_address, true), true, clipped };
return{ this_address, surface, x_offset, y_offset, w, h, address_is_bound(this_address, true), true, clipped };
}
}

View File

@ -878,6 +878,10 @@ namespace rsx
}
const auto extended_dimension = tex.get_extended_texture_dimension();
u16 depth = 0;
u16 tex_height = (u16)tex.height();
u16 tex_pitch = tex.pitch();
const u16 tex_width = tex.width();
if (!is_compressed_format)
{
@ -891,28 +895,44 @@ namespace rsx
LOG_ERROR(RSX, "Texture resides in render target memory, but requested type is not 2D (%d)", (u32)extended_dimension);
f32 internal_scale = (f32)texptr->get_native_pitch() / tex.pitch();
for (const auto& tex : m_rtts.m_bound_render_targets)
bool requires_processing = texptr->get_surface_width() != tex_width || texptr->get_surface_height() != tex_height;
if (!requires_processing)
{
if (std::get<0>(tex) == texaddr)
for (const auto& tex : m_rtts.m_bound_render_targets)
{
if (g_cfg.video.strict_rendering_mode)
if (std::get<0>(tex) == texaddr)
{
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
return{ create_temporary_subresource_view(cmd, texptr, format, 0, 0, texptr->width(), texptr->height()), texture_upload_context::framebuffer_storage, false, internal_scale };
}
else
{
//issue a texture barrier to ensure previous writes are visible
insert_texture_barrier();
break;
if (g_cfg.video.strict_rendering_mode)
{
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
requires_processing = true;
break;
}
else
{
//issue a texture barrier to ensure previous writes are visible
insert_texture_barrier();
break;
}
}
}
}
if (requires_processing)
{
const auto w = rsx::apply_resolution_scale(tex_width, true);
const auto h = rsx::apply_resolution_scale(tex_height, true);
return{ create_temporary_subresource_view(cmd, texptr, format, 0, 0, w, h), texture_upload_context::framebuffer_storage, false, internal_scale };
}
return{ texptr->get_view(), texture_upload_context::framebuffer_storage, false, internal_scale };
}
else
{
m_rtts.invalidate_surface_address(texaddr, false);
invalidate_address(texaddr, false, true, std::forward<Args>(extras)...);
}
}
if (auto texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
@ -923,12 +943,14 @@ namespace rsx
LOG_ERROR(RSX, "Texture resides in depth buffer memory, but requested type is not 2D (%d)", (u32)extended_dimension);
f32 internal_scale = (f32)texptr->get_native_pitch() / tex.pitch();
if (texaddr == std::get<0>(m_rtts.m_bound_depth_stencil))
bool requires_processing = texptr->get_surface_width() != tex_width || texptr->get_surface_height() != tex_height;
if (!requires_processing && texaddr == std::get<0>(m_rtts.m_bound_depth_stencil))
{
if (g_cfg.video.strict_rendering_mode)
{
LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr);
return{ create_temporary_subresource_view(cmd, texptr, format, 0, 0, texptr->width(), texptr->height()), texture_upload_context::framebuffer_storage, true, internal_scale };
requires_processing = true;
}
else
{
@ -937,18 +959,23 @@ namespace rsx
}
}
if (requires_processing)
{
const auto w = rsx::apply_resolution_scale(tex_width, true);
const auto h = rsx::apply_resolution_scale(tex_height, true);
return{ create_temporary_subresource_view(cmd, texptr, format, 0, 0, w, h), texture_upload_context::framebuffer_storage, true, internal_scale };
}
return{ texptr->get_view(), texture_upload_context::framebuffer_storage, true, internal_scale };
}
else
{
m_rtts.invalidate_surface_address(texaddr, true);
invalidate_address(texaddr, false, true, std::forward<Args>(extras)...);
}
}
}
u16 depth = 0;
u16 tex_height = (u16)tex.height();
u16 tex_pitch = tex.pitch();
const u16 tex_width = tex.width();
tex_pitch = is_compressed_format? (tex_size / tex_height) : tex_pitch; //NOTE: Compressed textures dont have a real pitch (tex_size = (w*h)/6)
if (tex_pitch == 0) tex_pitch = tex_width * get_format_block_size_in_bytes(format);
@ -987,9 +1014,10 @@ namespace rsx
if (rsc.surface)
{
//TODO: Check that this region is not cpu-dirty before doing a copy
if (!test_framebuffer(texaddr))
if (!test_framebuffer(rsc.base_address))
{
m_rtts.invalidate_surface_address(texaddr, rsc.is_depth_surface);
m_rtts.invalidate_surface_address(rsc.base_address, rsc.is_depth_surface);
invalidate_address(rsc.base_address, false, true, std::forward<Args>(extras)...);
}
else if (extended_dimension != rsx::texture_dimension_extended::texture_dimension_2d)
{
@ -1165,6 +1193,20 @@ namespace rsx
src_is_render_target = false;
}
if (src_is_render_target && !test_framebuffer(src_subres.base_address))
{
m_rtts.invalidate_surface_address(src_subres.base_address, src_subres.is_depth_surface);
invalidate_address(src_subres.base_address, false, true, std::forward<Args>(extras)...);
src_is_render_target = false;
}
if (dst_is_render_target && !test_framebuffer(dst_subres.base_address))
{
m_rtts.invalidate_surface_address(dst_subres.base_address, dst_subres.is_depth_surface);
invalidate_address(dst_subres.base_address, false, true, std::forward<Args>(extras)...);
dst_is_render_target = false;
}
//Always use GPU blit if src or dst is in the surface store
if (!g_cfg.video.use_gpu_texture_scaling && !(src_is_render_target || dst_is_render_target))
return false;

View File

@ -358,6 +358,12 @@ void GLGSRender::end()
std::lock_guard<std::mutex> lock(m_sampler_mutex);
void* unused = nullptr;
if (surface_store_tag != m_rtts.cache_tag)
{
m_samplers_dirty.store(true);
surface_store_tag = m_rtts.cache_tag;
}
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
if (m_samplers_dirty || m_textures_dirty[i])

View File

@ -379,6 +379,7 @@ private:
std::array<occlusion_query_info, 128> occlusion_query_data = {};
std::mutex m_sampler_mutex;
u64 surface_store_tag = 0;
std::atomic_bool m_samplers_dirty = {true};
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count> fs_sampler_state = {};
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_sampler_state = {};

View File

@ -1051,6 +1051,12 @@ void VKGSRender::end()
{
std::lock_guard<std::mutex> lock(m_sampler_mutex);
if (surface_store_tag != m_rtts.cache_tag)
{
m_samplers_dirty.store(true);
surface_store_tag = m_rtts.cache_tag;
}
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
if (m_samplers_dirty || m_textures_dirty[i])

View File

@ -130,6 +130,7 @@ private:
std::unique_ptr<vk::text_writer> m_text_writer;
std::mutex m_sampler_mutex;
u64 surface_store_tag = 0;
std::atomic_bool m_samplers_dirty = { true };
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count> fs_sampler_state = {};
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_sampler_state = {};

View File

@ -112,7 +112,10 @@ namespace vk
vk::image_view* get_raw_view()
{
return uploaded_image_view.get();
if (context != rsx::texture_upload_context::framebuffer_storage)
return uploaded_image_view.get();
else
return static_cast<vk::render_target*>(vram_texture)->get_view();
}
vk::image* get_raw_texture()