mirror of https://github.com/RPCS3/rpcs3.git
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:
parent
963a87fed5
commit
ec3e5c547f
|
@ -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 };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue