From 5f66d0b99655b0ae3a051c3fce3525aecaa9862b Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 12 Jun 2017 01:27:27 +0300 Subject: [PATCH] rsx/wip: Fix depth surface reuse and clearing (fixes shadows) --- rpcs3/Emu/RSX/Common/surface_store.h | 9 +++++++-- rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h | 7 ++++++- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 10 ++++++++-- rpcs3/Emu/RSX/GL/GLRenderTargets.h | 9 +++++---- rpcs3/Emu/RSX/VK/VKRenderTargets.h | 17 +++++++++++++++-- 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 1740276138..71b292ab81 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -115,6 +115,7 @@ namespace rsx command_list_type command_list, u32 address, surface_depth_format depth_format, size_t width, size_t height, + u32 previous_address, Args&&... extra_params) { auto It = m_depth_stencil_storage.find(address); @@ -123,7 +124,7 @@ namespace rsx surface_storage_type &ds = It->second; if (Traits::ds_has_format_width_height(ds, depth_format, width, height)) { - Traits::prepare_ds_for_drawing(command_list, Traits::get(ds)); + Traits::prepare_ds_for_drawing(command_list, Traits::get(ds), address != previous_address); return Traits::get(ds); } invalidated_resources.push_back(std::move(ds)); @@ -173,11 +174,15 @@ namespace rsx // Same for depth buffer if (std::get<1>(m_bound_depth_stencil) != nullptr) Traits::prepare_ds_for_sampling(command_list, std::get<1>(m_bound_depth_stencil)); + + const u32 old_zeta_address = std::get<0>(m_bound_depth_stencil); m_bound_depth_stencil = std::make_tuple(0, nullptr); + if (!address_z) return; + m_bound_depth_stencil = std::make_tuple(address_z, - bind_address_as_depth_stencil(command_list, address_z, depth_format, clip_width, clip_height, std::forward(extra_params)...)); + bind_address_as_depth_stencil(command_list, address_z, depth_format, clip_width, clip_height, old_zeta_address, std::forward(extra_params)...)); } /** diff --git a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h index fd036b34a8..a937c4bcec 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h @@ -18,6 +18,9 @@ struct render_target_traits using command_list_type = gsl::not_null; using download_buffer_object = std::tuple, HANDLE>; // heap offset, size, last_put_pos, fence, handle + //TODO: Move this somewhere else + bool depth_is_dirty = false; + static ComPtr create_new_surface( u32 address, @@ -97,10 +100,12 @@ struct render_target_traits static void prepare_ds_for_drawing( gsl::not_null command_list, - ID3D12Resource* ds) + ID3D12Resource* ds, bool surface_changed) { // set the resource as depth write command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE)); + + //TODO: Clear this surface if the depth address changed (Requires a partial rewrite) } static diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 16b4f0f202..76ffb94a54 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -349,11 +349,17 @@ void GLGSRender::end() gl::render_target *ds = std::get<1>(m_rtts.m_bound_depth_stencil); if (ds && !ds->cleared()) { + //Temporarily disable pixel tests + glDisable(GL_SCISSOR_TEST); glDepthMask(GL_TRUE); - glClearDepth(1.f); + + glClearDepth(1.0); + glClearStencil(0); - glClear(GL_DEPTH_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glDepthMask(rsx::method_registers.depth_write_enabled()); + glEnable(GL_SCISSOR_TEST); ds->set_cleared(); } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index 761bbfa0f3..aebd1c4728 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -65,9 +65,9 @@ namespace gl render_target() {} - void set_cleared() + void set_cleared(bool clear=true) { - is_cleared = true; + is_cleared = clear; } bool cleared() const @@ -227,7 +227,8 @@ struct gl_render_target_traits static void prepare_rtt_for_drawing(void *, gl::render_target*) {} static void prepare_rtt_for_sampling(void *, gl::render_target*) {} - static void prepare_ds_for_drawing(void *, gl::render_target*) {} + + static void prepare_ds_for_drawing(void *, gl::render_target *ds, bool surface_changed) { if (surface_changed) ds->set_cleared(false); } static void prepare_ds_for_sampling(void *, gl::render_target*) {} static @@ -238,7 +239,7 @@ struct gl_render_target_traits } static - bool ds_has_format_width_height(const std::unique_ptr &rtt, rsx::surface_depth_format surface_depth_stencil_format, size_t width, size_t height) + bool ds_has_format_width_height(const std::unique_ptr &rtt, rsx::surface_depth_format surface_depth_stencil_format, size_t width, size_t height) { // TODO: check format return rtt->width() == width && rtt->height() == height; diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 7c2ce06839..efa5e50105 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -128,10 +128,23 @@ namespace rsx change_image_layout(*pcmd, surface->value, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, range); } - static void prepare_ds_for_drawing(vk::command_buffer* pcmd, vk::render_target *surface) + static void prepare_ds_for_drawing(vk::command_buffer* pcmd, vk::render_target *surface, bool surface_changed) { VkImageSubresourceRange range = vk::get_image_subresource_range(0, 0, 1, 1, surface->attachment_aspect_flag); - change_image_layout(*pcmd, surface->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, range); + if (!surface_changed) + change_image_layout(*pcmd, surface->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, range); + else + { + change_image_layout(*pcmd, surface->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, range); + + //Clear the surface before drawing on it + VkClearDepthStencilValue clear_depth = {}; + clear_depth.depth = 1.f; + clear_depth.stencil = 0; + + vkCmdClearDepthStencilImage(*pcmd, surface->value, VK_IMAGE_LAYOUT_GENERAL, &clear_depth, 1, &range); + change_image_layout(*pcmd, surface->value, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, range); + } } static void prepare_ds_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface)