diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index dff47d5c1..fbc1a3047 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -1992,7 +1992,7 @@ bool GPU::RenderDisplay(GPUTexture* target, const GSVector4i draw_rect, bool pos g_gpu_device->UsesLowerLeftOrigin() ? GPUDevice::FlipToLowerLeft(draw_rect, target_height) : draw_rect; if (really_postfx) { - g_gpu_device->ClearRenderTarget(PostProcessing::DisplayChain.GetInputTexture(), 0); + g_gpu_device->ClearRenderTarget(PostProcessing::DisplayChain.GetInputTexture(), GPUDevice::DEFAULT_CLEAR_COLOR); g_gpu_device->SetRenderTarget(PostProcessing::DisplayChain.GetInputTexture()); } else @@ -2633,7 +2633,7 @@ bool GPU::RenderScreenshotToBuffer(u32 width, u32 height, const GSVector4i draw_ if (!render_texture) return false; - g_gpu_device->ClearRenderTarget(render_texture.get(), 0); + g_gpu_device->ClearRenderTarget(render_texture.get(), GPUDevice::DEFAULT_CLEAR_COLOR); // TODO: this should use copy shader instead. RenderDisplay(render_texture.get(), draw_rect, postfx); diff --git a/src/util/d3d11_device.cpp b/src/util/d3d11_device.cpp index b77cae55c..f9678a341 100644 --- a/src/util/d3d11_device.cpp +++ b/src/util/d3d11_device.cpp @@ -640,7 +640,7 @@ void D3D11Device::SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) } } -bool D3D11Device::BeginPresent(bool skip_present) +bool D3D11Device::BeginPresent(bool skip_present, u32 clear_color) { if (skip_present) return false; @@ -671,8 +671,7 @@ bool D3D11Device::BeginPresent(bool skip_present) if (m_vsync_mode == GPUVSyncMode::FIFO && m_gpu_timing_enabled) PopTimestampQuery(); - static constexpr float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color); + m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), GSVector4::rgba32(clear_color).F32); m_context->OMSetRenderTargets(1, m_swap_chain_rtv.GetAddressOf(), nullptr); s_stats.num_render_passes++; m_num_current_render_targets = 0; diff --git a/src/util/d3d11_device.h b/src/util/d3d11_device.h index 879ea1e45..71ed56fe1 100644 --- a/src/util/d3d11_device.h +++ b/src/util/d3d11_device.h @@ -104,7 +104,7 @@ public: bool SetGPUTimingEnabled(bool enabled) override; float GetAndResetAccumulatedGPUTime() override; - bool BeginPresent(bool skip_present) override; + bool BeginPresent(bool skip_present, u32 clear_color) override; void EndPresent(bool explicit_present) override; void SubmitPresent() override; diff --git a/src/util/d3d12_device.cpp b/src/util/d3d12_device.cpp index d3395e7b1..7c4089ea4 100644 --- a/src/util/d3d12_device.cpp +++ b/src/util/d3d12_device.cpp @@ -57,7 +57,6 @@ enum : u32 // We need to synchronize instance creation because of adapter enumeration from the UI thread. static std::mutex s_instance_mutex; -static constexpr D3D12_CLEAR_VALUE s_present_clear_color = {DXGI_FORMAT_R8G8B8A8_UNORM, {{0.0f, 0.0f, 0.0f, 1.0f}}}; static constexpr GPUTexture::Format s_swap_chain_format = GPUTexture::Format::RGBA8; // We just need to keep this alive, never reference it. @@ -987,7 +986,7 @@ void D3D12Device::RenderBlankFrame() m_current_swap_chain_buffer = ((m_current_swap_chain_buffer + 1) % static_cast(m_swap_chain_buffers.size())); D3D12Texture::TransitionSubresourceToState(cmdlist, swap_chain_buf.first.Get(), 0, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_RENDER_TARGET); - cmdlist->ClearRenderTargetView(swap_chain_buf.second, s_present_clear_color.Color, 0, nullptr); + cmdlist->ClearRenderTargetView(swap_chain_buf.second, GSVector4::cxpr(0.0f, 0.0f, 0.0f, 1.0f).F32, 0, nullptr); D3D12Texture::TransitionSubresourceToState(cmdlist, swap_chain_buf.first.Get(), 0, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); SubmitCommandList(false); @@ -1118,7 +1117,7 @@ void D3D12Device::SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) } } -bool D3D12Device::BeginPresent(bool frame_skip) +bool D3D12Device::BeginPresent(bool frame_skip, u32 clear_color) { if (InRenderPass()) EndRenderPass(); @@ -1147,7 +1146,7 @@ bool D3D12Device::BeginPresent(bool frame_skip) return false; } - BeginSwapChainRenderPass(); + BeginSwapChainRenderPass(clear_color); return true; } @@ -1844,7 +1843,7 @@ void D3D12Device::BeginRenderPass() SetInitialPipelineState(); } -void D3D12Device::BeginSwapChainRenderPass() +void D3D12Device::BeginSwapChainRenderPass(u32 clear_color) { DebugAssert(!InRenderPass()); @@ -1862,10 +1861,10 @@ void D3D12Device::BeginSwapChainRenderPass() m_current_textures[i]->TransitionToState(cmdlist, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); } - const D3D12_RENDER_PASS_RENDER_TARGET_DESC rt_desc = { - swap_chain_buf.second, - {D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR, {s_present_clear_color}}, - {D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE, {}}}; + D3D12_RENDER_PASS_RENDER_TARGET_DESC rt_desc = {swap_chain_buf.second, + {D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR, {}}, + {D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE, {}}}; + GSVector4::store(rt_desc.BeginningAccess.Clear.ClearValue.Color, GSVector4::rgba32(clear_color)); cmdlist->BeginRenderPass(1, &rt_desc, nullptr, D3D12_RENDER_PASS_FLAG_NONE); std::memset(m_current_render_targets.data(), 0, sizeof(m_current_render_targets)); diff --git a/src/util/d3d12_device.h b/src/util/d3d12_device.h index bad70729d..697dcd82b 100644 --- a/src/util/d3d12_device.h +++ b/src/util/d3d12_device.h @@ -126,7 +126,7 @@ public: bool SetGPUTimingEnabled(bool enabled) override; float GetAndResetAccumulatedGPUTime() override; - bool BeginPresent(bool skip_present) override; + bool BeginPresent(bool skip_present, u32 clear_color) override; void EndPresent(bool explicit_present) override; void SubmitPresent() override; @@ -276,7 +276,7 @@ private: // Ends a render pass if we're currently in one. // When Bind() is next called, the pass will be restarted. void BeginRenderPass(); - void BeginSwapChainRenderPass(); + void BeginSwapChainRenderPass(u32 clear_color); void EndRenderPass(); bool InRenderPass(); diff --git a/src/util/gpu_device.h b/src/util/gpu_device.h index b574b71ea..fee9ec7cf 100644 --- a/src/util/gpu_device.h +++ b/src/util/gpu_device.h @@ -532,6 +532,7 @@ public: static constexpr u32 MIN_TEXEL_BUFFER_ELEMENTS = 4 * 1024 * 512; static constexpr u32 MAX_RENDER_TARGETS = 4; static constexpr u32 MAX_IMAGE_RENDER_TARGETS = 2; + static constexpr u32 DEFAULT_CLEAR_COLOR = 0xFF000000u; static_assert(sizeof(GPUPipeline::GraphicsConfig::color_formats) == sizeof(GPUTexture::Format) * MAX_RENDER_TARGETS); GPUDevice(); @@ -700,7 +701,7 @@ public: virtual void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) = 0; /// Returns false if the window was completely occluded. - virtual bool BeginPresent(bool skip_present) = 0; + virtual bool BeginPresent(bool skip_present, u32 clear_color = DEFAULT_CLEAR_COLOR) = 0; virtual void EndPresent(bool explicit_submit) = 0; virtual void SubmitPresent() = 0; diff --git a/src/util/metal_device.h b/src/util/metal_device.h index e384267ea..4738907f4 100644 --- a/src/util/metal_device.h +++ b/src/util/metal_device.h @@ -265,7 +265,7 @@ public: void SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) override; - bool BeginPresent(bool skip_present) override; + bool BeginPresent(bool skip_present, u32 clear_color) override; void EndPresent(bool explicit_submit) override; void SubmitPresent() override; diff --git a/src/util/metal_device.mm b/src/util/metal_device.mm index 8ecc59f54..63bd7a1bd 100644 --- a/src/util/metal_device.mm +++ b/src/util/metal_device.mm @@ -2313,7 +2313,7 @@ id MetalDevice::GetBlitEncoder(bool is_inline) } } -bool MetalDevice::BeginPresent(bool skip_present) +bool MetalDevice::BeginPresent(bool skip_present, u32 clear_color) { @autoreleasepool { @@ -2338,9 +2338,11 @@ bool MetalDevice::BeginPresent(bool skip_present) SetViewportAndScissor(0, 0, m_window_info.surface_width, m_window_info.surface_height); // Set up rendering to layer. + const GSVector4 clear_color_v = GSVector4::rgba32(clear_color); id layer_texture = [m_layer_drawable texture]; m_layer_pass_desc.colorAttachments[0].texture = layer_texture; m_layer_pass_desc.colorAttachments[0].loadAction = MTLLoadActionClear; + m_layer_pass_desc.colorAttachments[0].clearColor = MTLClearColorMake(clear_color_v.r, clear_color_v.g, clear_color_v.g, clear_color_v.a); m_render_encoder = [[m_render_cmdbuf renderCommandEncoderWithDescriptor:m_layer_pass_desc] retain]; s_stats.num_render_passes++; std::memset(m_current_render_targets.data(), 0, sizeof(m_current_render_targets)); diff --git a/src/util/opengl_device.cpp b/src/util/opengl_device.cpp index 63e25c207..57a6be524 100644 --- a/src/util/opengl_device.cpp +++ b/src/util/opengl_device.cpp @@ -21,7 +21,6 @@ Log_SetChannel(OpenGLDevice); -static constexpr const std::array s_clear_color = {{0.0f, 0.0f, 0.0f, 1.0f}}; static constexpr const std::array s_draw_buffers = { {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}}; @@ -616,7 +615,7 @@ void OpenGLDevice::RenderBlankFrame() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glDisable(GL_SCISSOR_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClearBufferfv(GL_COLOR, 0, s_clear_color.data()); + glClearBufferfv(GL_COLOR, 0, GSVector4::cxpr(0.0f, 0.0f, 0.0f, 1.0f).F32); glColorMask(m_last_blend_state.write_r, m_last_blend_state.write_g, m_last_blend_state.write_b, m_last_blend_state.write_a); glEnable(GL_SCISSOR_TEST); @@ -742,7 +741,7 @@ void OpenGLDevice::DestroyBuffers() m_vertex_buffer.reset(); } -bool OpenGLDevice::BeginPresent(bool skip_present) +bool OpenGLDevice::BeginPresent(bool skip_present, u32 clear_color) { if (skip_present || m_window_info.type == WindowInfo::Type::Surfaceless) { @@ -758,7 +757,7 @@ bool OpenGLDevice::BeginPresent(bool skip_present) glBindFramebuffer(GL_FRAMEBUFFER, 0); glDisable(GL_SCISSOR_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClearBufferfv(GL_COLOR, 0, s_clear_color.data()); + glClearBufferfv(GL_COLOR, 0, GSVector4::rgba32(clear_color).F32); glColorMask(m_last_blend_state.write_r, m_last_blend_state.write_g, m_last_blend_state.write_b, m_last_blend_state.write_a); glEnable(GL_SCISSOR_TEST); diff --git a/src/util/opengl_device.h b/src/util/opengl_device.h index 04d1b2ed0..5bfd83892 100644 --- a/src/util/opengl_device.h +++ b/src/util/opengl_device.h @@ -104,7 +104,7 @@ public: void SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) override; - bool BeginPresent(bool skip_present) override; + bool BeginPresent(bool skip_present, u32 clear_color) override; void EndPresent(bool explicit_present) override; void SubmitPresent() override; diff --git a/src/util/vulkan_device.cpp b/src/util/vulkan_device.cpp index 224a16ef0..0660ed368 100644 --- a/src/util/vulkan_device.cpp +++ b/src/util/vulkan_device.cpp @@ -98,8 +98,6 @@ const std::array(GPUTexture::Format::MaxCount)> Vulka VK_FORMAT_A2R10G10B10_UNORM_PACK32, // RGB10A2 }; -static constexpr VkClearValue s_present_clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; - // Handles are always 64-bit, even on 32-bit platforms. static const VkRenderPass DYNAMIC_RENDERING_RENDER_PASS = ((VkRenderPass) static_cast(-1LL)); @@ -2423,7 +2421,7 @@ void VulkanDevice::SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) } } -bool VulkanDevice::BeginPresent(bool frame_skip) +bool VulkanDevice::BeginPresent(bool frame_skip, u32 clear_color) { if (InRenderPass()) EndRenderPass(); @@ -2486,7 +2484,7 @@ bool VulkanDevice::BeginPresent(bool frame_skip) } } - BeginSwapChainRenderPass(); + BeginSwapChainRenderPass(clear_color); return true; } @@ -3166,9 +3164,10 @@ void VulkanDevice::RenderBlankFrame() const VkImage image = m_swap_chain->GetCurrentImage(); static constexpr VkImageSubresourceRange srr = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + static constexpr VkClearColorValue clear_color = {{0.0f, 0.0f, 0.0f, 1.0f}}; VulkanTexture::TransitionSubresourcesToLayout(cmdbuf, image, GPUTexture::Type::RenderTarget, 0, 1, 0, 1, VulkanTexture::Layout::Undefined, VulkanTexture::Layout::TransferDst); - vkCmdClearColorImage(cmdbuf, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &s_present_clear_color.color, 1, &srr); + vkCmdClearColorImage(cmdbuf, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &srr); VulkanTexture::TransitionSubresourcesToLayout(cmdbuf, image, GPUTexture::Type::RenderTarget, 0, 1, 0, 1, VulkanTexture::Layout::TransferDst, VulkanTexture::Layout::PresentSrc); @@ -3527,7 +3526,7 @@ void VulkanDevice::BeginRenderPass() SetInitialPipelineState(); } -void VulkanDevice::BeginSwapChainRenderPass() +void VulkanDevice::BeginSwapChainRenderPass(u32 clear_color) { DebugAssert(!InRenderPass()); @@ -3547,18 +3546,20 @@ void VulkanDevice::BeginSwapChainRenderPass() m_current_textures[i]->TransitionToLayout(VulkanTexture::Layout::ShaderReadOnly); } + VkClearValue clear_value; + GSVector4::store(&clear_value.color.float32, GSVector4::rgba32(clear_color)); if (m_optional_extensions.vk_khr_dynamic_rendering) { - const VkRenderingAttachmentInfo ai = {VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, - nullptr, - m_swap_chain->GetCurrentImageView(), - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_RESOLVE_MODE_NONE_KHR, - VK_NULL_HANDLE, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_ATTACHMENT_LOAD_OP_CLEAR, - VK_ATTACHMENT_STORE_OP_STORE, - s_present_clear_color}; + VkRenderingAttachmentInfo ai = {VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, + nullptr, + m_swap_chain->GetCurrentImageView(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_RESOLVE_MODE_NONE_KHR, + VK_NULL_HANDLE, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_STORE, + clear_value}; const VkRenderingInfoKHR ri = {VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, nullptr, @@ -3586,7 +3587,7 @@ void VulkanDevice::BeginSwapChainRenderPass() m_swap_chain->GetCurrentFramebuffer(), {{0, 0}, {m_swap_chain->GetWidth(), m_swap_chain->GetHeight()}}, 1u, - &s_present_clear_color}; + &clear_value}; vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE); } diff --git a/src/util/vulkan_device.h b/src/util/vulkan_device.h index 8934b003f..be7a906ec 100644 --- a/src/util/vulkan_device.h +++ b/src/util/vulkan_device.h @@ -142,7 +142,7 @@ public: void SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) override; - bool BeginPresent(bool skip_present) override; + bool BeginPresent(bool skip_present, u32 clear_color) override; void EndPresent(bool explicit_present) override; void SubmitPresent() override; @@ -381,7 +381,7 @@ private: // Ends a render pass if we're currently in one. // When Bind() is next called, the pass will be restarted. void BeginRenderPass(); - void BeginSwapChainRenderPass(); + void BeginSwapChainRenderPass(u32 clear_color); void EndRenderPass(); bool InRenderPass();