diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 9c3b7ec7cd..a47781eace 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -169,6 +169,7 @@ void GLGSRender::init_buffers(bool skip_reading) const u16 clip_y = rsx::method_registers.surface_clip_origin_y(); framebuffer_status_valid = false; + m_framebuffer_state_contested = false; if (clip_horizontal == 0 || clip_vertical == 0) { @@ -207,10 +208,22 @@ void GLGSRender::init_buffers(bool skip_reading) if (surface_addresses[index] == depth_address && zeta_pitch >= required_z_pitch) { - //LOG_ERROR(RSX, "Some game dev set up the MRT to write to the same address as depth and color attachment. Not sure how to deal with that so the draw is discarded."); - //framebuffer_status_valid = false; - depth_address = 0; - break; + LOG_TRACE(RSX, "Framebuffer at 0x%X has aliasing color/depth targets, zeta_pitch = %d, color_pitch=%d", depth_address, zeta_pitch, pitchs[index]); + m_framebuffer_state_contested = true; + + if (rsx::method_registers.depth_test_enabled() || + (!rsx::method_registers.color_write_enabled() && rsx::method_registers.depth_write_enabled()) || + !!(rsx::method_registers.shader_control() & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)) + { + // Use address for depth data + surface_addresses[index] = 0; + } + else + { + // Use address for color data + depth_address = 0; + break; + } } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index a7ec2b7e0a..263fb4e0a7 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -188,6 +188,7 @@ namespace rsx bool m_transform_constants_dirty; bool m_textures_dirty[16]; bool m_vertex_textures_dirty[4]; + bool m_framebuffer_state_contested = false; protected: std::array get_color_surface_addresses() const; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 78d8256679..fbff89b6e1 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2315,6 +2315,7 @@ void VKGSRender::prepare_rtts() u32 clip_y = rsx::method_registers.surface_clip_origin_y(); framebuffer_status_valid = false; + m_framebuffer_state_contested = false; if (clip_width == 0 || clip_height == 0) { @@ -2354,10 +2355,23 @@ void VKGSRender::prepare_rtts() if (surface_addresses[index] == zeta_address && zeta_pitch >= required_z_pitch) { - //LOG_ERROR(RSX, "Some game dev set up the MRT to write to the same address as depth and color attachment. Not sure how to deal with that so the draw is discarded."); - //framebuffer_status_valid = false; - zeta_address = 0; - break; + LOG_TRACE(RSX, "Framebuffer at 0x%X has aliasing color/depth targets, zeta_pitch = %d, color_pitch=%d", zeta_address, zeta_pitch, surface_pitchs[index]); + m_framebuffer_state_contested = true; + + if (rsx::method_registers.depth_test_enabled() || + (!rsx::method_registers.color_write_enabled() && rsx::method_registers.depth_write_enabled()) || + !!(rsx::method_registers.shader_control() & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)) + { + // Use address for color data + zeta_address = 0; + break; + } + else + { + // Use address for depth data + // TODO: create a temporary render buffer for this to keep MRT outputs aligned + surface_addresses[index] = 0; + } } } diff --git a/rpcs3/Emu/RSX/rsx_decode.h b/rpcs3/Emu/RSX/rsx_decode.h index 2e33b0ac4a..88146b3ef8 100644 --- a/rpcs3/Emu/RSX/rsx_decode.h +++ b/rpcs3/Emu/RSX/rsx_decode.h @@ -3196,6 +3196,11 @@ struct registers_decoder { return bool(m_data.color_a); } + + bool color_write_enabled() const + { + return m_data.raw_data != 0; + } }; static std::string dump(decoded_type &&decoded_values) diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 8abf843c2b..aebce3cc08 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -471,6 +471,12 @@ namespace rsx rsx->m_rtts_dirty = true; } + void set_surface_options_dirty_bit(thread* rsx, u32, u32) + { + if (rsx->m_framebuffer_state_contested) + rsx->m_rtts_dirty = true; + } + template struct set_texture_dirty_bit { @@ -1598,6 +1604,9 @@ namespace rsx bind(); bind(); bind(); + bind(); + bind(); + bind(); //NV308A bind_range(); diff --git a/rpcs3/Emu/RSX/rsx_methods.h b/rpcs3/Emu/RSX/rsx_methods.h index b64903c348..640ea6a66f 100644 --- a/rpcs3/Emu/RSX/rsx_methods.h +++ b/rpcs3/Emu/RSX/rsx_methods.h @@ -345,6 +345,11 @@ namespace rsx return decode().color_a(); } + bool color_write_enabled() const + { + return decode().color_write_enabled(); + } + u8 clear_color_b() const { return decode().blue();