From 0e14fff7499eca0493da8025739a1b1a0fbeccd4 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 30 Oct 2024 03:54:32 +0100 Subject: [PATCH] [dxvk] Introduce tracking ID for resource tracking Replaces the existing bit masks, which is possible now because the CS thread is the only place where submissions happen now. This way we only count each resource once per submission, or twice in case a read access is followed by a write. This also fixes a potential tracking bug with shader-writeable resources. --- src/dxvk/dxvk_cmdlist.h | 9 +++++--- src/dxvk/dxvk_context.cpp | 47 ++++++++++++--------------------------- src/dxvk/dxvk_context.h | 18 --------------- src/dxvk/dxvk_sparse.h | 18 ++++++++++----- 4 files changed, 32 insertions(+), 60 deletions(-) diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index c17fe325d..e5be0a875 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -289,17 +289,20 @@ namespace dxvk { */ template void track(Rc&& object, DxvkAccess access) { - m_objectTracker.track(std::move(object), access, m_trackingId); + if (object->trackId(m_trackingId, access)) + m_objectTracker.track(std::move(object), access); } template void track(const Rc& object, DxvkAccess access) { - m_objectTracker.track(object.ptr(), access, m_trackingId); + if (object->trackId(m_trackingId, access)) + m_objectTracker.track(object.ptr(), access); } template void track(T* object, DxvkAccess access) { - m_objectTracker.track(object, access, m_trackingId); + if (object->trackId(m_trackingId, access)) + m_objectTracker.track(object, access); } /** diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 90bba9000..bea5043c9 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -5137,8 +5137,7 @@ namespace dxvk { descriptorInfo.image.imageView = VK_NULL_HANDLE; descriptorInfo.image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - if (m_rcTracked.set(binding.resourceBinding)) - m_cmd->track(res.sampler); + m_cmd->track(res.sampler); } else { descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle(); descriptorInfo.image.imageView = VK_NULL_HANDLE; @@ -5159,8 +5158,7 @@ namespace dxvk { descriptorInfo.image.imageView = viewHandle; descriptorInfo.image.imageLayout = res.imageView->image()->info().layout; - if (m_rcTracked.set(binding.resourceBinding)) - m_cmd->track(res.imageView->image(), DxvkAccess::Read); + m_cmd->track(res.imageView->image(), DxvkAccess::Read); } else { descriptorInfo.image.sampler = VK_NULL_HANDLE; descriptorInfo.image.imageView = VK_NULL_HANDLE; @@ -5181,10 +5179,8 @@ namespace dxvk { descriptorInfo.image.imageView = viewHandle; descriptorInfo.image.imageLayout = res.imageView->image()->info().layout; - if (m_rcTracked.set(binding.resourceBinding)) { - m_cmd->track(res.imageView->image(), (binding.access & vk::AccessWriteMask) - ? DxvkAccess::Write : DxvkAccess::Read); - } + m_cmd->track(res.imageView->image(), (binding.access & vk::AccessWriteMask) + ? DxvkAccess::Write : DxvkAccess::Read); } else { descriptorInfo.image.sampler = VK_NULL_HANDLE; descriptorInfo.image.imageView = VK_NULL_HANDLE; @@ -5205,10 +5201,8 @@ namespace dxvk { descriptorInfo.image.imageView = viewHandle; descriptorInfo.image.imageLayout = res.imageView->image()->info().layout; - if (m_rcTracked.set(binding.resourceBinding)) { - m_cmd->track(res.sampler); - m_cmd->track(res.imageView->image(), DxvkAccess::Read); - } + m_cmd->track(res.sampler); + m_cmd->track(res.imageView->image(), DxvkAccess::Read); } else { descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle(); descriptorInfo.image.imageView = VK_NULL_HANDLE; @@ -5222,8 +5216,7 @@ namespace dxvk { if (res.bufferView != nullptr) { descriptorInfo.texelBuffer = res.bufferView->handle(); - if (m_rcTracked.set(binding.resourceBinding)) - m_cmd->track(res.bufferView->buffer(), DxvkAccess::Read); + m_cmd->track(res.bufferView->buffer(), DxvkAccess::Read); } else { descriptorInfo.texelBuffer = VK_NULL_HANDLE; } @@ -5235,10 +5228,8 @@ namespace dxvk { if (res.bufferView != nullptr) { descriptorInfo.texelBuffer = res.bufferView->handle(); - if (m_rcTracked.set(binding.resourceBinding)) { - m_cmd->track(res.bufferView->buffer(), (binding.access & vk::AccessWriteMask) - ? DxvkAccess::Write : DxvkAccess::Read); - } + m_cmd->track(res.bufferView->buffer(), (binding.access & vk::AccessWriteMask) + ? DxvkAccess::Write : DxvkAccess::Read); } else { descriptorInfo.texelBuffer = VK_NULL_HANDLE; } @@ -5250,8 +5241,7 @@ namespace dxvk { if (res.bufferSlice.length()) { descriptorInfo = res.bufferSlice.getDescriptor(); - if (m_rcTracked.set(binding.resourceBinding)) - m_cmd->track(res.bufferSlice.buffer(), DxvkAccess::Read); + m_cmd->track(res.bufferSlice.buffer(), DxvkAccess::Read); } else { descriptorInfo.buffer.buffer = VK_NULL_HANDLE; descriptorInfo.buffer.offset = 0; @@ -5265,10 +5255,8 @@ namespace dxvk { if (res.bufferSlice.length()) { descriptorInfo = res.bufferSlice.getDescriptor(); - if (m_rcTracked.set(binding.resourceBinding)) { - m_cmd->track(res.bufferSlice.buffer(), (binding.access & vk::AccessWriteMask) - ? DxvkAccess::Write : DxvkAccess::Read); - } + m_cmd->track(res.bufferSlice.buffer(), (binding.access & vk::AccessWriteMask) + ? DxvkAccess::Write : DxvkAccess::Read); } else { descriptorInfo.buffer.buffer = VK_NULL_HANDLE; descriptorInfo.buffer.offset = 0; @@ -5552,9 +5540,7 @@ namespace dxvk { m_state.vi.indexType); } - if (m_vbTracked.set(MaxNumVertexBindings)) - m_cmd->track(m_state.vi.indexBuffer.buffer(), DxvkAccess::Read); - + m_cmd->track(m_state.vi.indexBuffer.buffer(), DxvkAccess::Read); return true; } @@ -5591,8 +5577,7 @@ namespace dxvk { newDynamicStrides &= strides[i] >= m_state.vi.vertexExtents[i]; } - if (m_vbTracked.set(binding)) - m_cmd->track(m_state.vi.vertexBuffers[binding].buffer(), DxvkAccess::Read); + m_cmd->track(m_state.vi.vertexBuffers[binding].buffer(), DxvkAccess::Read); } else { buffers[i] = VK_NULL_HANDLE; offsets[i] = 0; @@ -6669,10 +6654,6 @@ namespace dxvk { void DxvkContext::beginCurrentCommands() { - // Mark all resources as untracked - m_vbTracked.clear(); - m_rcTracked.clear(); - // The current state of the internal command buffer is // undefined, so we have to bind and set up everything // before any draw or dispatch command is recorded. diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index c70c6b4d7..c08e9bf19 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -177,9 +177,6 @@ namespace dxvk { void bindIndexBuffer( DxvkBufferSlice&& buffer, VkIndexType indexType) { - if (!m_state.vi.indexBuffer.matchesBuffer(buffer)) - m_vbTracked.clr(MaxNumVertexBindings); - m_state.vi.indexBuffer = std::move(buffer); m_state.vi.indexType = indexType; @@ -218,11 +215,6 @@ namespace dxvk { VkShaderStageFlags stages, uint32_t slot, DxvkBufferSlice&& buffer) { - bool needsUpdate = !m_rc[slot].bufferSlice.matchesBuffer(buffer); - - if (likely(needsUpdate)) - m_rcTracked.clr(slot); - m_rc[slot].bufferSlice = std::move(buffer); m_descriptorState.dirtyBuffers(stages); @@ -261,7 +253,6 @@ namespace dxvk { } m_rc[slot].imageView = std::move(view); - m_rcTracked.clr(slot); m_descriptorState.dirtyViews(stages); } @@ -288,8 +279,6 @@ namespace dxvk { m_rc[slot].bufferView = nullptr; } - m_rcTracked.clr(slot); - m_descriptorState.dirtyViews(stages); } @@ -307,7 +296,6 @@ namespace dxvk { uint32_t slot, Rc&& sampler) { m_rc[slot].sampler = std::move(sampler); - m_rcTracked.clr(slot); m_descriptorState.dirtyViews(stages); } @@ -371,9 +359,6 @@ namespace dxvk { uint32_t binding, DxvkBufferSlice&& buffer, uint32_t stride) { - if (!m_state.vi.vertexBuffers[binding].matchesBuffer(buffer)) - m_vbTracked.clr(binding); - m_state.vi.vertexBuffers[binding] = std::move(buffer); m_state.vi.vertexStrides[binding] = stride; m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers); @@ -1413,9 +1398,6 @@ namespace dxvk { DxvkRenderTargetLayouts m_rtLayouts = { }; - DxvkBindingSet m_vbTracked; - DxvkBindingSet m_rcTracked; - std::vector m_deferredClears; std::vector m_descriptorWrites; diff --git a/src/dxvk/dxvk_sparse.h b/src/dxvk/dxvk_sparse.h index 11f5d8036..a6efd031f 100644 --- a/src/dxvk/dxvk_sparse.h +++ b/src/dxvk/dxvk_sparse.h @@ -542,10 +542,18 @@ namespace dxvk { * command list and optimize certain transfer operations. * \param [in] trackingId Tracking ID * \param [in] access Tracked access + * \returns \c true if the tracking ID was updated, or \c false + * if the resource was already tracked with the same ID. */ - void trackId(uint64_t trackingId, DxvkAccess access) { + bool trackId(uint64_t trackingId, DxvkAccess access) { // Encode write access in the least significant bit - m_trackId = std::max(m_trackId, (trackingId << 1u) + uint64_t(access == DxvkAccess::Write)); + uint64_t trackId = (trackingId << 1u) + uint64_t(access == DxvkAccess::Write); + + if (trackId <= m_trackId) + return false; + + m_trackId = trackId; + return true; } /** @@ -623,15 +631,13 @@ namespace dxvk { public: template - explicit DxvkResourceRef(Rc&& object, DxvkAccess access, uint64_t trackingId) + explicit DxvkResourceRef(Rc&& object, DxvkAccess access) : 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, uint64_t trackingId) + explicit DxvkResourceRef(DxvkPagedResource* object, DxvkAccess access) : m_ptr(reinterpret_cast(object) | uintptr_t(access)) { - object->trackId(trackingId, access); object->acquire(access); }