diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index a5eb437f..86344a10 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -287,17 +287,17 @@ namespace dxvk { */ template void track(Rc&& object, DxvkAccess access) { - m_objectTracker.track(std::move(object), access); + m_objectTracker.track(std::move(object), access, m_trackingId); } template void track(const Rc& object, DxvkAccess access) { - m_objectTracker.track(object.ptr(), access); + m_objectTracker.track(object.ptr(), access, m_trackingId); } template void track(T* object, DxvkAccess access) { - m_objectTracker.track(object, access); + m_objectTracker.track(object, access, m_trackingId); } /** @@ -1061,6 +1061,11 @@ namespace dxvk { m_descriptorPools.push_back({ pool, manager }); } + + void setTrackingId(uint64_t id) { + m_trackingId = id; + } + private: DxvkDevice* m_device; @@ -1073,6 +1078,7 @@ namespace dxvk { DxvkCommandSubmissionInfo m_cmd; PresenterSync m_wsiSemaphores = { }; + uint64_t m_trackingId = 0u; DxvkObjectTracker m_objectTracker; DxvkSignalTracker m_signalTracker; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index e75356de..bceb33b2 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1383,6 +1383,8 @@ namespace dxvk { Rc prevAllocation = buffer->assignStorage(std::move(slice)); m_cmd->track(std::move(prevAllocation)); + buffer->resetTracking(); + // We also need to update all bindings that the buffer // may be bound to either directly or through views. VkBufferUsageFlags usage = buffer->info().usage & @@ -1475,6 +1477,8 @@ namespace dxvk { if (usageInfo.stableGpuAddress) m_common->memoryManager().lockResourceGpuAddress(image->storage()); + + image->resetTracking(); } @@ -6712,6 +6716,8 @@ namespace dxvk { m_state.gp.pipeline = nullptr; m_state.cp.pipeline = nullptr; + + m_cmd->setTrackingId(++m_trackingId); } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index c5fbb2c2..e74d0cc7 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1383,6 +1383,8 @@ namespace dxvk { Rc m_device; DxvkObjects* m_common; + + uint64_t m_trackingId = 0u; Rc m_cmd; Rc m_zeroBuffer; diff --git a/src/dxvk/dxvk_sparse.h b/src/dxvk/dxvk_sparse.h index 237ced82..aa1f1764 100644 --- a/src/dxvk/dxvk_sparse.h +++ b/src/dxvk/dxvk_sparse.h @@ -512,7 +512,7 @@ namespace dxvk { force_inline bool isInUse(DxvkAccess access) const { return m_useCount.load(std::memory_order_acquire) >= getIncrement(access); } - + /** * \brief Tries to acquire reference * @@ -535,6 +535,43 @@ namespace dxvk { return Rc::unsafeCreate(this); } + /** + * \brief Sets tracked command list ID + * + * Used to work out if a resource has been used in the current + * command list and optimize certain transfer operations. + * \param [in] trackingId Tracking ID + * \param [in] access Tracked access + */ + void trackId(uint64_t trackingId, DxvkAccess access) { + // Encode write access in the least significant bit + m_trackId = (trackingId << 1u) + uint64_t(access == DxvkAccess::Write); + } + + /** + * \brief Checks whether a resource has been tracked + * + * \param [in] trackingId Current tracking ID + * \param [in] access Destination access + * \returns \c true if the resource has been used in a way that + * prevents recordering commands with the given resource access. + */ + bool isTracked(uint64_t trackingId, DxvkAccess access) const { + // We actually want to check for read access here so that this check only + // fails if the resource hasn't been used or if both accesses are read-only. + return m_trackId >= (trackingId << 1u) + uint64_t(access != DxvkAccess::Write); + } + + /** + * \brief Resets tracking + * + * Marks the resource as unused in the current command list. + * Should be done when assigning new backing storage. + */ + void resetTracking() { + m_trackId = 0u; + } + /** * \brief Queries sparse page table * @@ -562,6 +599,7 @@ namespace dxvk { private: std::atomic m_useCount = { 0u }; + uint64_t m_trackId = { 0u }; uint64_t m_cookie = { 0u }; static constexpr uint64_t getIncrement(DxvkAccess access) { @@ -585,13 +623,15 @@ namespace dxvk { public: template - explicit DxvkResourceRef(Rc&& object, DxvkAccess access) + explicit DxvkResourceRef(Rc&& object, DxvkAccess access, uint64_t trackingId) : m_ptr(reinterpret_cast(static_cast(object.ptr())) | uintptr_t(access)) { + object->trackId(trackingId, access); object.unsafeExtract()->convertRef(DxvkAccess::None, access); } - explicit DxvkResourceRef(DxvkPagedResource* object, DxvkAccess access) + explicit DxvkResourceRef(DxvkPagedResource* object, DxvkAccess access, uint64_t trackingId) : m_ptr(reinterpret_cast(object) | uintptr_t(access)) { + object->trackId(trackingId, access); object->acquire(access); }