diff --git a/src/d3d9/d3d9_common_buffer.h b/src/d3d9/d3d9_common_buffer.h index 8f24d9c8..043731e3 100644 --- a/src/d3d9/d3d9_common_buffer.h +++ b/src/d3d9/d3d9_common_buffer.h @@ -187,6 +187,28 @@ namespace dxvk { void PreLoad(); + /** + * \brief Tracks sequence number + * + * Stores which CS chunk the resource was last used on. + * \param [in] Seq Sequence number + */ + void TrackMappingBufferSequenceNumber(uint64_t Seq) { + m_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 GetMappingBufferSequenceNumber() const { + return m_seq; + } + private: Rc CreateBuffer() const; @@ -220,6 +242,8 @@ namespace dxvk { uint32_t m_lockCount = 0; + uint64_t m_seq = 0ull; + }; } \ No newline at end of file diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index f4d14115..1a1f2d5d 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -435,6 +435,31 @@ namespace dxvk { static VkImageType GetImageTypeFromResourceType( D3DRESOURCETYPE Dimension); + /** + * \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 TrackMappingBufferSequenceNumber(UINT Subresource, uint64_t Seq) { + if (Subresource < m_seqs.size()) + m_seqs[Subresource] = 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 GetMappingBufferSequenceNumber(UINT Subresource) { + return Subresource < m_seqs.size() + ? m_seqs[Subresource] + : 0ull; + } + private: D3D9DeviceEx* m_device; @@ -448,6 +473,8 @@ namespace dxvk { Rc> m_buffers; D3D9SubresourceArray< DxvkBufferSliceHandle> m_mappedSlices; + D3D9SubresourceArray< + uint64_t> m_seqs = { }; D3D9_VK_FORMAT_MAPPING m_mapping; diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 78e4732f..1fb74c77 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -926,6 +926,7 @@ namespace dxvk { }); dstTexInfo->SetWrittenByGPU(dst->GetSubresource(), true); + TrackTextureMappingBufferSequenceNumber(dstTexInfo, dst->GetSubresource()); return D3D_OK; } @@ -2694,6 +2695,7 @@ namespace dxvk { } dst->SetWrittenByGPU(true); + TrackBufferMappingBufferSequenceNumber(dst); return D3D_OK; } @@ -4545,6 +4547,8 @@ namespace dxvk { if (pResource->IsAutomaticMip()) MarkTextureMipsDirty(pResource); + TrackTextureMappingBufferSequenceNumber(pResource, Subresource); + return D3D_OK; } @@ -4745,7 +4749,7 @@ namespace dxvk { void D3D9DeviceEx::EmitCsChunk(DxvkCsChunkRef&& chunk) { - m_csThread.dispatchChunk(std::move(chunk)); + m_csSeqNum = m_csThread.dispatchChunk(std::move(chunk)); m_csIsBusy = true; } @@ -7349,4 +7353,24 @@ namespace dxvk { return D3D_OK; } + void D3D9DeviceEx::TrackBufferMappingBufferSequenceNumber( + D3D9CommonBuffer* pResource) { + uint64_t sequenceNumber = GetCurrentSequenceNumber(); + pResource->TrackMappingBufferSequenceNumber(sequenceNumber); + } + + void D3D9DeviceEx::TrackTextureMappingBufferSequenceNumber( + D3D9CommonTexture* pResource, + UINT Subresource) { + uint64_t sequenceNumber = GetCurrentSequenceNumber(); + pResource->TrackMappingBufferSequenceNumber(Subresource, sequenceNumber); + } + + uint64_t D3D9DeviceEx::GetCurrentSequenceNumber() { + // We do not flush empty chunks, so if we are tracking a resource + // immediately after a flush, we need to use the sequence number + // of the previously submitted chunk to prevent deadlocks. + return m_csChunk->empty() ? m_csSeqNum : m_csSeqNum + 1; + } + } diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index 2455315a..d12c59dc 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -1120,6 +1120,15 @@ namespace dxvk { void UpdateSamplerDepthModeSpecConstant(uint32_t value); + void TrackBufferMappingBufferSequenceNumber( + D3D9CommonBuffer* pResource); + + void TrackTextureMappingBufferSequenceNumber( + D3D9CommonTexture* pResource, + UINT Subresource); + + uint64_t GetCurrentSequenceNumber(); + Com m_parent; D3DDEVTYPE m_deviceType; HWND m_window; @@ -1242,6 +1251,7 @@ namespace dxvk { = dxvk::high_resolution_clock::now(); DxvkCsThread m_csThread; DxvkCsChunkRef m_csChunk; + uint64_t m_csSeqNum = 0ull; bool m_csIsBusy = false; std::atomic m_availableMemory = { 0 };