From d33dac569cf217523c4866f1427452f335f796b3 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 9 Feb 2022 02:54:32 +0100 Subject: [PATCH] [d3d11] Track last staging resource usage with a sequence number --- src/d3d11/d3d11_buffer.h | 17 +++++++++ src/d3d11/d3d11_context.cpp | 41 +++++++++++++++++--- src/d3d11/d3d11_context.h | 7 ++++ src/d3d11/d3d11_context_def.cpp | 13 +++++++ src/d3d11/d3d11_context_def.h | 7 ++++ src/d3d11/d3d11_context_imm.cpp | 15 +++++++- src/d3d11/d3d11_context_imm.h | 15 ++++++-- src/d3d11/d3d11_texture.cpp | 2 +- src/d3d11/d3d11_texture.h | 66 ++++++++++++++++++++++++++++++--- 9 files changed, 168 insertions(+), 15 deletions(-) diff --git a/src/d3d11/d3d11_buffer.h b/src/d3d11/d3d11_buffer.h index 8bb30aef..c0472fd6 100644 --- a/src/d3d11/d3d11_buffer.h +++ b/src/d3d11/d3d11_buffer.h @@ -1,5 +1,6 @@ #pragma once +#include "../dxvk/dxvk_cs.h" #include "../dxvk/dxvk_device.h" #include "../d3d10/d3d10_buffer.h" @@ -117,6 +118,21 @@ namespace dxvk { return &m_d3d10; } + bool HasSequenceNumber() const { + return m_mapMode != D3D11_COMMON_BUFFER_MAP_MODE_NONE + && !(m_desc.MiscFlags & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS) + && !(m_desc.BindFlags); + } + + void TrackSequenceNumber(uint64_t Seq) { + m_seq = Seq; + } + + uint64_t GetSequenceNumber() { + return HasSequenceNumber() ? m_seq + : DxvkCsThread::SynchronizeAll; + } + /** * \brief Normalizes buffer description * @@ -134,6 +150,7 @@ namespace dxvk { Rc m_buffer; Rc m_soCounter; DxvkBufferSliceHandle m_mapped; + uint64_t m_seq = 0ull; D3D11DXGIResource m_resource; D3D10Buffer m_d3d10; diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 9e81070b..2acd52f6 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -473,6 +473,9 @@ namespace dxvk { cSrcSlice.offset(), sizeof(uint32_t)); }); + + if (buf->HasSequenceNumber()) + TrackBufferSequenceNumber(buf); } @@ -1003,8 +1006,8 @@ namespace dxvk { return; } - const D3D11CommonTexture* dstTextureInfo = GetCommonTexture(pDstResource); - const D3D11CommonTexture* srcTextureInfo = GetCommonTexture(pSrcResource); + D3D11CommonTexture* dstTextureInfo = GetCommonTexture(pDstResource); + D3D11CommonTexture* srcTextureInfo = GetCommonTexture(pSrcResource); const DXGI_VK_FORMAT_INFO dstFormatInfo = m_parent->LookupFormat(dstDesc.Format, DXGI_VK_FORMAT_MODE_ANY); const DXGI_VK_FORMAT_INFO srcFormatInfo = m_parent->LookupFormat(srcDesc.Format, DXGI_VK_FORMAT_MODE_ANY); @@ -1067,6 +1070,9 @@ namespace dxvk { ctx->resolveImage(cDstImage, cSrcImage, region, cFormat); }); } + + if (dstTextureInfo->HasSequenceNumber()) + TrackTextureSequenceNumber(dstTextureInfo, DstSubresource); } @@ -3276,6 +3282,11 @@ namespace dxvk { cSrcBuffer.length()); } }); + + if (pDstBuffer->HasSequenceNumber()) + TrackBufferSequenceNumber(pDstBuffer); + if (pSrcBuffer->HasSequenceNumber()) + TrackBufferSequenceNumber(pSrcBuffer); } @@ -3510,6 +3521,20 @@ namespace dxvk { } } } + + if (pDstTexture->HasSequenceNumber()) { + for (uint32_t i = 0; i < pDstLayers->layerCount; i++) { + TrackTextureSequenceNumber(pDstTexture, D3D11CalcSubresource( + pDstLayers->mipLevel, pDstLayers->baseArrayLayer + i, pDstTexture->Desc()->MipLevels)); + } + } + + if (pSrcTexture->HasSequenceNumber()) { + for (uint32_t i = 0; i < pSrcLayers->layerCount; i++) { + TrackTextureSequenceNumber(pSrcTexture, D3D11CalcSubresource( + pSrcLayers->mipLevel, pSrcLayers->baseArrayLayer + i, pSrcTexture->Desc()->MipLevels)); + } + } } @@ -3580,6 +3605,9 @@ namespace dxvk { cBufferSlice.length()); }); } + + if (pDstBuffer->HasSequenceNumber()) + TrackBufferSequenceNumber(pDstBuffer); } @@ -3644,6 +3672,9 @@ namespace dxvk { DxvkBufferSlice StagingBuffer) { bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING; + uint32_t dstSubresource = D3D11CalcSubresource(pDstSubresource->mipLevel, + pDstSubresource->arrayLayer, pDstTexture->Desc()->MipLevels); + if (dstIsImage) { EmitCs([ cDstImage = pDstTexture->GetImage(), @@ -3675,9 +3706,6 @@ namespace dxvk { // format metadata, so deal with it manually here. VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstSubresource->mipLevel); - uint32_t dstSubresource = D3D11CalcSubresource(pDstSubresource->mipLevel, - pDstSubresource->arrayLayer, pDstTexture->Desc()->MipLevels); - auto dstFormat = pDstTexture->GetPackedFormat(); auto dstFormatInfo = imageFormatInfo(dstFormat); @@ -3725,6 +3753,9 @@ namespace dxvk { srcPlaneOffset += util::flattenImageExtent(blockCount) * elementSize; } } + + if (pDstTexture->HasSequenceNumber()) + TrackTextureSequenceNumber(pDstTexture, dstSubresource); } diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index 4c853afb..82500721 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -1070,6 +1070,13 @@ namespace dxvk { virtual void EmitCsChunk(DxvkCsChunkRef&& chunk) = 0; + virtual void TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource) = 0; + + virtual void TrackBufferSequenceNumber( + D3D11Buffer* pResource) = 0; + }; } diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index 450b1992..ff5c4ac5 100644 --- a/src/d3d11/d3d11_context_def.cpp +++ b/src/d3d11/d3d11_context_def.cpp @@ -420,6 +420,19 @@ namespace dxvk { } + void D3D11DeferredContext::TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource) { + // TODO implement + } + + + void D3D11DeferredContext::TrackBufferSequenceNumber( + D3D11Buffer* pResource) { + // TODO implement + } + + DxvkCsChunkFlags D3D11DeferredContext::GetCsChunkFlags( D3D11Device* pDevice) { return pDevice->GetOptions()->dcSingleUseMode diff --git a/src/d3d11/d3d11_context_def.h b/src/d3d11/d3d11_context_def.h index a5c67ff6..5189571d 100644 --- a/src/d3d11/d3d11_context_def.h +++ b/src/d3d11/d3d11_context_def.h @@ -134,6 +134,13 @@ namespace dxvk { void EmitCsChunk(DxvkCsChunkRef&& chunk); + void TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource); + + void TrackBufferSequenceNumber( + D3D11Buffer* pResource); + static DxvkCsChunkFlags GetCsChunkFlags( D3D11Device* pDevice); diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp index b254f41c..5d77f2e6 100644 --- a/src/d3d11/d3d11_context_imm.cpp +++ b/src/d3d11/d3d11_context_imm.cpp @@ -594,11 +594,24 @@ namespace dxvk { void D3D11ImmediateContext::EmitCsChunk(DxvkCsChunkRef&& chunk) { - m_csThread.dispatchChunk(std::move(chunk)); + m_csSeqNum = m_csThread.dispatchChunk(std::move(chunk)); m_csIsBusy = true; } + void D3D11ImmediateContext::TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource) { + pResource->TrackSequenceNumber(Subresource, m_csSeqNum + 1); + } + + + void D3D11ImmediateContext::TrackBufferSequenceNumber( + D3D11Buffer* pResource) { + pResource->TrackSequenceNumber(m_csSeqNum + 1); + } + + void D3D11ImmediateContext::FlushImplicit(BOOL StrongHint) { // Flush only if the GPU is about to go idle, in // order to keep the number of submissions low. diff --git a/src/d3d11/d3d11_context_imm.h b/src/d3d11/d3d11_context_imm.h index b47ef12a..c268b8ed 100644 --- a/src/d3d11/d3d11_context_imm.h +++ b/src/d3d11/d3d11_context_imm.h @@ -116,11 +116,13 @@ namespace dxvk { private: - DxvkCsThread m_csThread; - bool m_csIsBusy = false; + DxvkCsThread m_csThread; + uint64_t m_csSeqNum = 0ull; + bool m_csIsBusy = false; Rc m_eventSignal; - uint64_t m_eventCount = 0; + uint64_t m_eventCount = 0ull; + dxvk::high_resolution_clock::time_point m_lastFlush = dxvk::high_resolution_clock::now(); @@ -161,6 +163,13 @@ namespace dxvk { void EmitCsChunk(DxvkCsChunkRef&& chunk); + void TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource); + + void TrackBufferSequenceNumber( + D3D11Buffer* pResource); + void FlushImplicit(BOOL StrongHint); void SignalEvent(HANDLE hEvent); diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index 7b6d02c1..14c1379c 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -163,7 +163,7 @@ namespace dxvk { if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) m_buffers.push_back(CreateMappedBuffer(j)); - m_mapTypes.push_back(D3D11_MAP(~0u)); + m_mapInfo.push_back({ D3D11_MAP(~0u), 0ull }); } } } diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index f4df6e12..e6115279 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -1,5 +1,6 @@ #pragma once +#include "../dxvk/dxvk_cs.h" #include "../dxvk/dxvk_device.h" #include "../d3d10/d3d10_texture.h" @@ -164,8 +165,8 @@ namespace dxvk { * \returns Current map mode of that subresource */ D3D11_MAP GetMapType(UINT Subresource) const { - return Subresource < m_mapTypes.size() - ? D3D11_MAP(m_mapTypes[Subresource]) + return Subresource < m_mapInfo.size() + ? D3D11_MAP(m_mapInfo[Subresource].mapType) : D3D11_MAP(~0u); } @@ -176,8 +177,8 @@ namespace dxvk { * \param [in] MapType The map type */ void SetMapType(UINT Subresource, D3D11_MAP MapType) { - if (Subresource < m_mapTypes.size()) - m_mapTypes[Subresource] = MapType; + if (Subresource < m_mapInfo.size()) + m_mapInfo[Subresource].mapType = MapType; } /** @@ -240,6 +241,56 @@ namespace dxvk { return m_packedFormat; } + /** + * \brief Checks whether the resource is eligible for tracking + * + * Mapped resources with no bind flags can be tracked so that + * mapping them will not necessarily cause a CS thread sync. + * \returns \c true if tracking is supported for this resource + */ + bool HasSequenceNumber() const { + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_NONE) + return false; + + // For buffer-mapped images we only need to track copies to + // and from that buffer, so we can safely ignore bind flags + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER) + return true; + + // Otherwise we can only do accurate tracking if the + // image cannot be used in the rendering pipeline. + return m_desc.BindFlags == 0; + } + + /** + * \brief Tracks sequence number for a given subresource + * + * Stores which CS chunk the resource was last used on. + * \param [in] Subresource Subresource index + * \param [in] Seq Sequence number + */ + void TrackSequenceNumber(UINT Subresource, uint64_t Seq) { + if (Subresource < m_mapInfo.size()) + m_mapInfo[Subresource].seq = Seq; + } + + /** + * \brief Queries sequence number for a given subresource + * + * Returns which CS chunk the resource was last used on. + * \param [in] Subresource Subresource index + * \returns Sequence number for the given subresource + */ + uint64_t GetSequenceNumber(UINT Subresource) { + if (HasSequenceNumber()) { + return Subresource < m_buffers.size() + ? m_mapInfo[Subresource].seq + : 0ull; + } else { + return DxvkCsThread::SynchronizeAll; + } + } + /** * \brief Computes pixel offset into mapped buffer * @@ -327,6 +378,11 @@ namespace dxvk { DxvkBufferSliceHandle slice; }; + struct MappedInfo { + D3D11_MAP mapType; + uint64_t seq; + }; + ID3D11Resource* m_interface; D3D11Device* m_device; D3D11_RESOURCE_DIMENSION m_dimension; @@ -337,7 +393,7 @@ namespace dxvk { Rc m_image; std::vector m_buffers; - std::vector m_mapTypes; + std::vector m_mapInfo; MappedBuffer CreateMappedBuffer( UINT MipLevel) const;