From 81e7a8d1f66e31ffe784bcdabd646be16d86fcea Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 23 Jun 2019 18:55:49 +0200 Subject: [PATCH] [dxvk] Avoid redundant resource tracking Only tracks a shader resource if the resource bound to the slot has actually changed, or if we began recording a new command buffer. Reduces the number of atomic operations in some games. --- src/dxvk/dxvk_context.cpp | 37 ++++++++++++++++++++++++++----------- src/dxvk/dxvk_context.h | 5 +++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 03c502dc..065d0d0f 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -41,6 +41,9 @@ namespace dxvk { void DxvkContext::beginRecording(const Rc& cmdList) { m_cmd = cmdList; m_cmd->beginRecording(); + + // Mark all resources as untracked + m_rcTracked.clear(); // The current state of the internal command buffer is // undefined, so we have to bind and set up everything @@ -161,6 +164,7 @@ namespace dxvk { const DxvkBufferSlice& buffer) { if (!m_rc[slot].bufferSlice.matches(buffer)) { m_rc[slot].bufferSlice = buffer; + m_rcTracked.clr(slot); m_flags.set( DxvkContextFlag::CpDirtyResources, @@ -180,6 +184,7 @@ namespace dxvk { m_rc[slot].bufferSlice = bufferView != nullptr ? bufferView->slice() : DxvkBufferSlice(); + m_rcTracked.clr(slot); m_flags.set( DxvkContextFlag::CpDirtyResources, @@ -192,7 +197,8 @@ namespace dxvk { uint32_t slot, const Rc& sampler) { if (m_rc[slot].sampler != sampler) { - m_rc[slot].sampler = sampler; + m_rc[slot].sampler = sampler; + m_rcTracked.clr(slot); m_flags.set( DxvkContextFlag::CpDirtyResources, @@ -3549,7 +3555,8 @@ namespace dxvk { m_descInfos[i].image.imageView = VK_NULL_HANDLE; m_descInfos[i].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - m_cmd->trackResource(res.sampler); + if (m_rcTracked.set(binding.slot)) + m_cmd->trackResource(res.sampler); } else { updatePipelineState |= bindMask.clr(i); m_descInfos[i].image = m_device->dummySamplerDescriptor(); @@ -3567,8 +3574,10 @@ namespace dxvk { if (unlikely(res.imageView->imageHandle() == depthImage)) m_descInfos[i].image.imageLayout = depthLayout; - m_cmd->trackResource(res.imageView); - m_cmd->trackResource(res.imageView->image()); + if (m_rcTracked.set(binding.slot)) { + m_cmd->trackResource(res.imageView); + m_cmd->trackResource(res.imageView->image()); + } } else { updatePipelineState |= bindMask.clr(i); m_descInfos[i].image = m_device->dummyImageViewDescriptor(binding.view); @@ -3586,9 +3595,11 @@ namespace dxvk { if (unlikely(res.imageView->imageHandle() == depthImage)) m_descInfos[i].image.imageLayout = depthLayout; - m_cmd->trackResource(res.sampler); - m_cmd->trackResource(res.imageView); - m_cmd->trackResource(res.imageView->image()); + if (m_rcTracked.set(binding.slot)) { + m_cmd->trackResource(res.sampler); + m_cmd->trackResource(res.imageView); + m_cmd->trackResource(res.imageView->image()); + } } else { updatePipelineState |= bindMask.clr(i); m_descInfos[i].image = m_device->dummyImageSamplerDescriptor(binding.view); @@ -3602,8 +3613,10 @@ namespace dxvk { res.bufferView->updateView(); m_descInfos[i].texelBuffer = res.bufferView->handle(); - m_cmd->trackResource(res.bufferView); - m_cmd->trackResource(res.bufferView->buffer()); + if (m_rcTracked.set(binding.slot)) { + m_cmd->trackResource(res.bufferView); + m_cmd->trackResource(res.bufferView->buffer()); + } } else { updatePipelineState |= bindMask.clr(i); m_descInfos[i].texelBuffer = m_device->dummyBufferViewDescriptor(); @@ -3615,7 +3628,8 @@ namespace dxvk { updatePipelineState |= bindMask.set(i); m_descInfos[i] = res.bufferSlice.getDescriptor(); - m_cmd->trackResource(res.bufferSlice.buffer()); + if (m_rcTracked.set(binding.slot)) + m_cmd->trackResource(res.bufferSlice.buffer()); } else { updatePipelineState |= bindMask.clr(i); m_descInfos[i].buffer = m_device->dummyBufferDescriptor(); @@ -3628,7 +3642,8 @@ namespace dxvk { m_descInfos[i] = res.bufferSlice.getDescriptor(); m_descInfos[i].buffer.offset = 0; - m_cmd->trackResource(res.bufferSlice.buffer()); + if (m_rcTracked.set(binding.slot)) + m_cmd->trackResource(res.bufferSlice.buffer()); } else { updatePipelineState |= bindMask.clr(i); m_descInfos[i].buffer = m_device->dummyBufferDescriptor(); diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 041de51b..0d7e94c9 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -994,6 +994,8 @@ namespace dxvk { VkDescriptorSet m_gpSet = VK_NULL_HANDLE; VkDescriptorSet m_cpSet = VK_NULL_HANDLE; + DxvkBindingSet m_rcTracked; + std::array m_rc; std::array m_descInfos; std::array m_descOffsets; @@ -1086,6 +1088,9 @@ namespace dxvk { void updateGraphicsShaderResources(); void updateGraphicsShaderDescriptors(); + + void updateShaderSamplers( + const DxvkPipelineLayout* layout); void updateShaderResources( VkPipelineBindPoint bindPoint,