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, shader_write = 1,
transfer_read = 2, transfer_read = 2,
transfer_write = 4, transfer_write = 4,
// Arbitrary r/w flags, use with caution.
memory_write = 8,
memory_read = 16
}; };
private: private:
// Meta // Meta
enum enum
{ {
all_writes = (shader_write | transfer_write), all_writes = (shader_write | transfer_write | memory_write),
all_reads = (shader_read | transfer_read), all_reads = (shader_read | transfer_read | memory_read),
all_transfer = (transfer_read | transfer_write) all_transfer = (transfer_read | transfer_write)
}; };
@ -80,6 +84,11 @@ namespace rsx
return !(value_ & ~all_transfer); 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 bool operator == (const surface_access& other) const
{ {
return value_ == other.value_; 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() ? const bool memory_load = is_depth_surface() ?
!!g_cfg.video.read_depth_buffer : !!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)) if (dirty() && (read_access || state_flags & rsx::surface_state_flags::erase_bkgnd))
{ {
// Initialize memory contents if we did not find anything usable // Initialize memory contents if we did not find anything usable
initialize_memory(cmd, true); initialize_memory(cmd, access);
on_write(); 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(); const auto area = section.dst_rect();
if (area.x1 > 0 || area.y1 > 0 || unsigned(area.x2) < width() || unsigned(area.y2) < height()) if (area.x1 > 0 || area.y1 > 0 || unsigned(area.x2) < width() || unsigned(area.y2) < height())
{ {
initialize_memory(cmd, false); initialize_memory(cmd, access);
} }
else else
{ {

View file

@ -49,7 +49,7 @@ namespace gl
{ {
void clear_memory(gl::command_context& cmd); void clear_memory(gl::command_context& cmd);
void load_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: public:
render_target(GLuint width, GLuint height, GLenum sized_format, rsx::format_class format_class) 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; 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 is_depth = is_depth_surface();
const bool should_read_buffers = is_depth ? !!g_cfg.video.read_depth_buffer : !!g_cfg.video.read_color_buffers; 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); 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 // Only clear the resolve surface if reading from it, otherwise it's a waste
clear_memory(cmd, get_resolve_target_safe(cmd)); 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) 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 is_depth = is_depth_surface();
const bool should_read_buffers = is_depth ? !!g_cfg.video.read_depth_buffer : !!g_cfg.video.read_color_buffers; 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) if (current_layout == VK_IMAGE_LAYOUT_GENERAL)
{ {
@ -433,7 +432,7 @@ namespace vk
if (state_flags & rsx::surface_state_flags::erase_bkgnd) if (state_flags & rsx::surface_state_flags::erase_bkgnd)
{ {
// NOTE: This step CAN introduce MSAA flags! // NOTE: This step CAN introduce MSAA flags!
initialize_memory(cmd, read_access); initialize_memory(cmd, access);
ensure(state_flags == rsx::surface_state_flags::ready); ensure(state_flags == rsx::surface_state_flags::ready);
on_write(rsx::get_shared_tag(), static_cast<rsx::surface_state_flags>(msaa_flags)); 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 (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 // Only do this step when read access is required
get_resolve_target_safe(cmd); get_resolve_target_safe(cmd);
@ -450,7 +449,7 @@ namespace vk
} }
else if (msaa_flags & rsx::surface_state_flags::require_unresolve) 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 // Only do this step when it is needed to start rendering
ensure(resolve_surface); ensure(resolve_surface);
@ -521,7 +520,7 @@ namespace vk
else if (state_flags & rsx::surface_state_flags::erase_bkgnd) else if (state_flags & rsx::surface_state_flags::erase_bkgnd)
{ {
// Might introduce MSAA flags // Might introduce MSAA flags
initialize_memory(cmd, false); initialize_memory(cmd, rsx::surface_access::memory_write);
ensure(state_flags == rsx::surface_state_flags::ready); ensure(state_flags == rsx::surface_state_flags::ready);
} }
@ -549,14 +548,14 @@ namespace vk
clear_rw_barrier(); clear_rw_barrier();
state_flags |= rsx::surface_state_flags::erase_bkgnd; 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); ensure(state_flags == rsx::surface_state_flags::ready);
} }
// NOTE: Optimize flag relates to stencil resolve/unresolve for NVIDIA. // NOTE: Optimize flag relates to stencil resolve/unresolve for NVIDIA.
on_write_copy(newest_tag, optimize_copy); 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 // Write barrier, must initialize
unresolve(cmd); unresolve(cmd);

View file

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