rsx: Fix transfer barriers not triggering resolve target initialization

This commit is contained in:
kd-11 2021-05-12 00:44:40 +03:00 committed by kd-11
parent f7b845d49c
commit 1a73b0a0da
5 changed files with 26 additions and 18 deletions

View File

@ -46,14 +46,18 @@ namespace rsx
shader_write = 1,
transfer_read = 2,
transfer_write = 4,
// Arbitrary r/w flags, use with caution.
memory_write = 8,
memory_read = 16
};
private:
// Meta
enum
{
all_writes = (shader_write | transfer_write),
all_reads = (shader_read | transfer_read),
all_writes = (shader_write | transfer_write | memory_write),
all_reads = (shader_read | transfer_read | memory_read),
all_transfer = (transfer_read | transfer_write)
};
@ -80,6 +84,11 @@ namespace rsx
return !(value_ & ~all_transfer);
}
inline bool is_transfer_or_read() const // Special; reads and transfers generate MSAA load operations
{
return !(value_ & ~(all_transfer | all_reads));
}
bool operator == (const surface_access& other) const
{
return value_ == other.value_;

View File

@ -438,7 +438,7 @@ void gl::render_target::load_memory(gl::command_context& cmd)
}
}
void gl::render_target::initialize_memory(gl::command_context& cmd, bool /*read_access*/)
void gl::render_target::initialize_memory(gl::command_context& cmd, rsx::surface_access /*access*/)
{
const bool memory_load = is_depth_surface() ?
!!g_cfg.video.read_depth_buffer :
@ -478,7 +478,7 @@ void gl::render_target::memory_barrier(gl::command_context& cmd, rsx::surface_ac
if (dirty() && (read_access || state_flags & rsx::surface_state_flags::erase_bkgnd))
{
// Initialize memory contents if we did not find anything usable
initialize_memory(cmd, true);
initialize_memory(cmd, access);
on_write();
}
@ -523,7 +523,7 @@ void gl::render_target::memory_barrier(gl::command_context& cmd, rsx::surface_ac
const auto area = section.dst_rect();
if (area.x1 > 0 || area.y1 > 0 || unsigned(area.x2) < width() || unsigned(area.y2) < height())
{
initialize_memory(cmd, false);
initialize_memory(cmd, access);
}
else
{

View File

@ -49,7 +49,7 @@ namespace gl
{
void clear_memory(gl::command_context& cmd);
void load_memory(gl::command_context& cmd);
void initialize_memory(gl::command_context& cmd, bool read_access);
void initialize_memory(gl::command_context& cmd, rsx::surface_access access);
public:
render_target(GLuint width, GLuint height, GLenum sized_format, rsx::format_class format_class)

View File

@ -279,7 +279,7 @@ namespace vk
state_flags &= ~rsx::surface_state_flags::erase_bkgnd;
}
void render_target::initialize_memory(vk::command_buffer& cmd, bool read_access)
void render_target::initialize_memory(vk::command_buffer& cmd, rsx::surface_access access)
{
const bool is_depth = is_depth_surface();
const bool should_read_buffers = is_depth ? !!g_cfg.video.read_depth_buffer : !!g_cfg.video.read_color_buffers;
@ -288,7 +288,7 @@ namespace vk
{
clear_memory(cmd, this);
if (read_access && samples() > 1)
if (samples() > 1 && access.is_transfer_or_read())
{
// Only clear the resolve surface if reading from it, otherwise it's a waste
clear_memory(cmd, get_resolve_target_safe(cmd));
@ -369,7 +369,6 @@ namespace vk
void render_target::memory_barrier(vk::command_buffer& cmd, rsx::surface_access access)
{
const bool read_access = access.is_read();
const bool is_depth = is_depth_surface();
const bool should_read_buffers = is_depth ? !!g_cfg.video.read_depth_buffer : !!g_cfg.video.read_color_buffers;
@ -385,7 +384,7 @@ namespace vk
}
}
if (!read_access && write_barrier_sync_tag != 0)
if (access == rsx::surface_access::shader_write && write_barrier_sync_tag != 0)
{
if (current_layout == VK_IMAGE_LAYOUT_GENERAL)
{
@ -433,7 +432,7 @@ namespace vk
if (state_flags & rsx::surface_state_flags::erase_bkgnd)
{
// NOTE: This step CAN introduce MSAA flags!
initialize_memory(cmd, read_access);
initialize_memory(cmd, access);
ensure(state_flags == rsx::surface_state_flags::ready);
on_write(rsx::get_shared_tag(), static_cast<rsx::surface_state_flags>(msaa_flags));
@ -441,7 +440,7 @@ namespace vk
if (msaa_flags & rsx::surface_state_flags::require_resolve)
{
if (read_access)
if (access.is_transfer_or_read())
{
// Only do this step when read access is required
get_resolve_target_safe(cmd);
@ -450,7 +449,7 @@ namespace vk
}
else if (msaa_flags & rsx::surface_state_flags::require_unresolve)
{
if (!read_access)
if (access == rsx::surface_access::shader_write)
{
// Only do this step when it is needed to start rendering
ensure(resolve_surface);
@ -521,7 +520,7 @@ namespace vk
else if (state_flags & rsx::surface_state_flags::erase_bkgnd)
{
// Might introduce MSAA flags
initialize_memory(cmd, false);
initialize_memory(cmd, rsx::surface_access::memory_write);
ensure(state_flags == rsx::surface_state_flags::ready);
}
@ -549,14 +548,14 @@ namespace vk
clear_rw_barrier();
state_flags |= rsx::surface_state_flags::erase_bkgnd;
initialize_memory(cmd, read_access);
initialize_memory(cmd, access);
ensure(state_flags == rsx::surface_state_flags::ready);
}
// NOTE: Optimize flag relates to stencil resolve/unresolve for NVIDIA.
on_write_copy(newest_tag, optimize_copy);
if (!read_access && samples() > 1)
if (access == rsx::surface_access::shader_write && samples() > 1)
{
// Write barrier, must initialize
unresolve(cmd);

View File

@ -34,8 +34,8 @@ namespace vk
void clear_memory(vk::command_buffer& cmd, vk::image* surface);
// Load memory from cell and use to initialize the surface
void load_memory(vk::command_buffer& cmd);
// Generic - chooses whether to clear or load
void initialize_memory(vk::command_buffer& cmd, bool read_access);
// Generic - chooses whether to clear or load.
void initialize_memory(vk::command_buffer& cmd, rsx::surface_access access);
public:
u64 frame_tag = 0; // frame id when invalidated, 0 if not invalid