diff --git a/UnleashedRecomp/gpu/rhi/rt64_d3d12.cpp b/UnleashedRecomp/gpu/rhi/rt64_d3d12.cpp index 8b43fad..bed7c9e 100644 --- a/UnleashedRecomp/gpu/rhi/rt64_d3d12.cpp +++ b/UnleashedRecomp/gpu/rhi/rt64_d3d12.cpp @@ -1947,6 +1947,11 @@ namespace RT64 { d3d->BuildRaytracingAccelerationStructure(&buildDesc, 0, nullptr); } + void D3D12CommandList::discardTexture(const RenderTexture* texture) { + const D3D12Texture* interfaceTexture = static_cast(texture); + d3d->DiscardResource(interfaceTexture->d3d, nullptr); + } + void D3D12CommandList::checkDescriptorHeaps() { if (!descriptorHeapsSet) { ID3D12DescriptorHeap *descriptorHeaps[] = { device->viewHeapAllocator->shaderHeap, device->samplerHeapAllocator->shaderHeap }; diff --git a/UnleashedRecomp/gpu/rhi/rt64_d3d12.h b/UnleashedRecomp/gpu/rhi/rt64_d3d12.h index 0efa0e1..fcc9f58 100644 --- a/UnleashedRecomp/gpu/rhi/rt64_d3d12.h +++ b/UnleashedRecomp/gpu/rhi/rt64_d3d12.h @@ -192,6 +192,7 @@ namespace RT64 { void resolveTextureRegion(const RenderTexture *dstTexture, uint32_t dstX, uint32_t dstY, const RenderTexture *srcTexture, const RenderRect *srcRect) override; void buildBottomLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, const RenderBottomLevelASBuildInfo &buildInfo) override; void buildTopLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, RenderBufferReference instancesBuffer, const RenderTopLevelASBuildInfo &buildInfo) override; + void discardTexture(const RenderTexture* texture) override; void checkDescriptorHeaps(); void notifyDescriptorHeapWasChangedExternally(); void checkTopology(); diff --git a/UnleashedRecomp/gpu/rhi/rt64_render_interface.h b/UnleashedRecomp/gpu/rhi/rt64_render_interface.h index b57cc34..ae066c9 100644 --- a/UnleashedRecomp/gpu/rhi/rt64_render_interface.h +++ b/UnleashedRecomp/gpu/rhi/rt64_render_interface.h @@ -138,7 +138,8 @@ namespace RT64 { virtual void resolveTextureRegion(const RenderTexture *dstTexture, uint32_t dstX, uint32_t dstY, const RenderTexture *srcTexture, const RenderRect *srcRect = nullptr) = 0; virtual void buildBottomLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, const RenderBottomLevelASBuildInfo &buildInfo) = 0; virtual void buildTopLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, RenderBufferReference instancesBuffer, const RenderTopLevelASBuildInfo &buildInfo) = 0; - + virtual void discardTexture(const RenderTexture* texture) = 0; // D3D12 only. + // Concrete implementation shortcuts. inline void barriers(RenderBarrierStages stages, const RenderBufferBarrier &barrier) { barriers(stages, &barrier, 1, nullptr, 0); diff --git a/UnleashedRecomp/gpu/rhi/rt64_vulkan.cpp b/UnleashedRecomp/gpu/rhi/rt64_vulkan.cpp index 79a1d82..82978c6 100644 --- a/UnleashedRecomp/gpu/rhi/rt64_vulkan.cpp +++ b/UnleashedRecomp/gpu/rhi/rt64_vulkan.cpp @@ -3088,6 +3088,10 @@ namespace RT64 { vkCmdBuildAccelerationStructuresKHR(vk, 1, &buildGeometryInfo, &buildRangeInfoPtr); } + void VulkanCommandList::discardTexture(const RenderTexture* texture) { + // Not required in Vulkan. + } + void VulkanCommandList::checkActiveRenderPass() { assert(targetFramebuffer != nullptr); diff --git a/UnleashedRecomp/gpu/rhi/rt64_vulkan.h b/UnleashedRecomp/gpu/rhi/rt64_vulkan.h index 52f5aaa..c89e90a 100644 --- a/UnleashedRecomp/gpu/rhi/rt64_vulkan.h +++ b/UnleashedRecomp/gpu/rhi/rt64_vulkan.h @@ -295,6 +295,7 @@ namespace RT64 { void resolveTextureRegion(const RenderTexture *dstTexture, uint32_t dstX, uint32_t dstY, const RenderTexture *srcTexture, const RenderRect *srcRect) override; void buildBottomLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, const RenderBottomLevelASBuildInfo &buildInfo) override; void buildTopLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, RenderBufferReference instancesBuffer, const RenderTopLevelASBuildInfo &buildInfo) override; + void discardTexture(const RenderTexture* texture) override; void checkActiveRenderPass(); void endActiveRenderPass(); void setDescriptorSet(VkPipelineBindPoint bindPoint, const VulkanPipelineLayout *pipelineLayout, const RenderDescriptorSet *descriptorSet, uint32_t setIndex); diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index dc308da..6d7f3b2 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -1105,8 +1105,9 @@ static GuestSurface* CreateSurface(uint32_t width, uint32_t height, uint32_t for surface->height = height; surface->format = desc.format; surface->sampleCount = desc.multisampling.sampleCount; + surface->pendingDiscard = true; - if (multiSample != 0 && desc.format == RenderFormat::D32_FLOAT) + if (desc.multisampling.sampleCount != RenderSampleCount::COUNT_1 && desc.format == RenderFormat::D32_FLOAT) { RenderTextureViewDesc viewDesc; viewDesc.dimension = RenderTextureViewDimension::TEXTURE_2D; @@ -1296,6 +1297,18 @@ static void FlushFramebuffer() FlushBarriers(); + if (g_renderTarget != nullptr && g_renderTarget->pendingDiscard) + { + commandList->discardTexture(g_renderTarget->textureHolder.get()); + g_renderTarget->pendingDiscard = false; + } + + if (g_depthStencil != nullptr && g_depthStencil->pendingDiscard) + { + commandList->discardTexture(g_depthStencil->textureHolder.get()); + g_depthStencil->pendingDiscard = false; + } + if (g_dirtyStates.renderTargetAndDepthStencil) { GuestSurface* framebufferContainer = nullptr; diff --git a/UnleashedRecomp/gpu/video.h b/UnleashedRecomp/gpu/video.h index 9c62087..1772342 100644 --- a/UnleashedRecomp/gpu/video.h +++ b/UnleashedRecomp/gpu/video.h @@ -150,9 +150,10 @@ struct GuestSurface : GuestResource uint32_t height = 0; RenderFormat format = RenderFormat::UNKNOWN; ankerl::unordered_dense::map> framebuffers; - bool pendingBarrier = true; RenderSampleCounts sampleCount = RenderSampleCount::COUNT_1; uint32_t descriptorIndex = 0; + bool pendingBarrier = true; + bool pendingDiscard = false; }; enum GuestDeclType