mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-08 07:51:28 +12:00
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
7 changed files with 100 additions and 27 deletions
|
@ -17,6 +17,7 @@ namespace rsx
|
||||||
struct surface_subresource_storage
|
struct surface_subresource_storage
|
||||||
{
|
{
|
||||||
surface_type surface = nullptr;
|
surface_type surface = nullptr;
|
||||||
|
u32 base_address = 0;
|
||||||
|
|
||||||
u16 x = 0;
|
u16 x = 0;
|
||||||
u16 y = 0;
|
u16 y = 0;
|
||||||
|
@ -29,8 +30,8 @@ namespace rsx
|
||||||
|
|
||||||
surface_subresource_storage() {}
|
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_subresource_storage(u32 addr, 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)
|
: 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::tuple<u32, surface_type> m_bound_depth_stencil = {};
|
||||||
|
|
||||||
std::list<surface_storage_type> invalidated_resources;
|
std::list<surface_storage_type> invalidated_resources;
|
||||||
|
u64 cache_tag = 0ull;
|
||||||
|
|
||||||
surface_store() = default;
|
surface_store() = default;
|
||||||
~surface_store() = default;
|
~surface_store() = default;
|
||||||
|
@ -272,6 +274,8 @@ namespace rsx
|
||||||
// u32 clip_x = clip_horizontal_reg;
|
// u32 clip_x = clip_horizontal_reg;
|
||||||
// u32 clip_y = clip_vertical_reg;
|
// u32 clip_y = clip_vertical_reg;
|
||||||
|
|
||||||
|
cache_tag++;
|
||||||
|
|
||||||
// Make previous RTTs sampleable
|
// Make previous RTTs sampleable
|
||||||
for (std::tuple<u32, surface_type> &rtt : m_bound_render_targets)
|
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));
|
invalidated_resources.push_back(std::move(It->second));
|
||||||
m_render_targets_storage.erase(It);
|
m_render_targets_storage.erase(It);
|
||||||
|
|
||||||
|
cache_tag++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,6 +517,8 @@ namespace rsx
|
||||||
{
|
{
|
||||||
invalidated_resources.push_back(std::move(It->second));
|
invalidated_resources.push_back(std::move(It->second));
|
||||||
m_depth_stencil_storage.erase(It);
|
m_depth_stencil_storage.erase(It);
|
||||||
|
|
||||||
|
cache_tag++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,6 +543,9 @@ namespace rsx
|
||||||
{
|
{
|
||||||
invalidated_resources.push_back(std::move(It->second));
|
invalidated_resources.push_back(std::move(It->second));
|
||||||
m_render_targets_storage.erase(It);
|
m_render_targets_storage.erase(It);
|
||||||
|
|
||||||
|
cache_tag++;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -544,6 +555,9 @@ namespace rsx
|
||||||
{
|
{
|
||||||
invalidated_resources.push_back(std::move(It->second));
|
invalidated_resources.push_back(std::move(It->second));
|
||||||
m_depth_stencil_storage.erase(It);
|
m_depth_stencil_storage.erase(It);
|
||||||
|
|
||||||
|
cache_tag++;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -725,11 +739,11 @@ namespace rsx
|
||||||
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
|
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
|
||||||
continue;
|
continue;
|
||||||
else
|
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))
|
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))
|
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
|
||||||
continue;
|
continue;
|
||||||
else
|
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))
|
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();
|
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)
|
if (!is_compressed_format)
|
||||||
{
|
{
|
||||||
|
@ -891,6 +895,10 @@ namespace rsx
|
||||||
LOG_ERROR(RSX, "Texture resides in render target memory, but requested type is not 2D (%d)", (u32)extended_dimension);
|
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();
|
f32 internal_scale = (f32)texptr->get_native_pitch() / tex.pitch();
|
||||||
|
bool requires_processing = texptr->get_surface_width() != tex_width || texptr->get_surface_height() != tex_height;
|
||||||
|
|
||||||
|
if (!requires_processing)
|
||||||
|
{
|
||||||
for (const auto& tex : m_rtts.m_bound_render_targets)
|
for (const auto& tex : m_rtts.m_bound_render_targets)
|
||||||
{
|
{
|
||||||
if (std::get<0>(tex) == texaddr)
|
if (std::get<0>(tex) == texaddr)
|
||||||
|
@ -898,7 +906,8 @@ namespace rsx
|
||||||
if (g_cfg.video.strict_rendering_mode)
|
if (g_cfg.video.strict_rendering_mode)
|
||||||
{
|
{
|
||||||
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", 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 };
|
requires_processing = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -908,11 +917,22 @@ 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, false, internal_scale };
|
||||||
|
}
|
||||||
|
|
||||||
return{ texptr->get_view(), texture_upload_context::framebuffer_storage, false, internal_scale };
|
return{ texptr->get_view(), texture_upload_context::framebuffer_storage, false, internal_scale };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m_rtts.invalidate_surface_address(texaddr, false);
|
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))
|
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);
|
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();
|
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)
|
if (g_cfg.video.strict_rendering_mode)
|
||||||
{
|
{
|
||||||
LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -937,17 +959,22 @@ 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 };
|
return{ texptr->get_view(), texture_upload_context::framebuffer_storage, true, internal_scale };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m_rtts.invalidate_surface_address(texaddr, true);
|
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)
|
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);
|
if (tex_pitch == 0) tex_pitch = tex_width * get_format_block_size_in_bytes(format);
|
||||||
|
@ -987,9 +1014,10 @@ namespace rsx
|
||||||
if (rsc.surface)
|
if (rsc.surface)
|
||||||
{
|
{
|
||||||
//TODO: Check that this region is not cpu-dirty before doing a copy
|
//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)
|
else if (extended_dimension != rsx::texture_dimension_extended::texture_dimension_2d)
|
||||||
{
|
{
|
||||||
|
@ -1165,6 +1193,20 @@ namespace rsx
|
||||||
src_is_render_target = false;
|
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
|
//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))
|
if (!g_cfg.video.use_gpu_texture_scaling && !(src_is_render_target || dst_is_render_target))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -358,6 +358,12 @@ void GLGSRender::end()
|
||||||
std::lock_guard<std::mutex> lock(m_sampler_mutex);
|
std::lock_guard<std::mutex> lock(m_sampler_mutex);
|
||||||
void* unused = nullptr;
|
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)
|
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||||
{
|
{
|
||||||
if (m_samplers_dirty || m_textures_dirty[i])
|
if (m_samplers_dirty || m_textures_dirty[i])
|
||||||
|
|
|
@ -379,6 +379,7 @@ private:
|
||||||
std::array<occlusion_query_info, 128> occlusion_query_data = {};
|
std::array<occlusion_query_info, 128> occlusion_query_data = {};
|
||||||
|
|
||||||
std::mutex m_sampler_mutex;
|
std::mutex m_sampler_mutex;
|
||||||
|
u64 surface_store_tag = 0;
|
||||||
std::atomic_bool m_samplers_dirty = {true};
|
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::fragment_textures_count> fs_sampler_state = {};
|
||||||
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_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);
|
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)
|
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||||
{
|
{
|
||||||
if (m_samplers_dirty || m_textures_dirty[i])
|
if (m_samplers_dirty || m_textures_dirty[i])
|
||||||
|
|
|
@ -130,6 +130,7 @@ private:
|
||||||
std::unique_ptr<vk::text_writer> m_text_writer;
|
std::unique_ptr<vk::text_writer> m_text_writer;
|
||||||
|
|
||||||
std::mutex m_sampler_mutex;
|
std::mutex m_sampler_mutex;
|
||||||
|
u64 surface_store_tag = 0;
|
||||||
std::atomic_bool m_samplers_dirty = { true };
|
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::fragment_textures_count> fs_sampler_state = {};
|
||||||
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_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()
|
vk::image_view* get_raw_view()
|
||||||
{
|
{
|
||||||
|
if (context != rsx::texture_upload_context::framebuffer_storage)
|
||||||
return uploaded_image_view.get();
|
return uploaded_image_view.get();
|
||||||
|
else
|
||||||
|
return static_cast<vk::render_target*>(vram_texture)->get_view();
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::image* get_raw_texture()
|
vk::image* get_raw_texture()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue