From f4b91817fe276332885271563cb48fa0389b2ab8 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 1 Mar 2023 12:10:48 +0100 Subject: [PATCH] [dxvk] Create dummy sampler and buffer on demand We only need the dummy buffer for transform feedback, all other cases are handled by null descriptors. May save a memory allocation. --- src/dxvk/dxvk_unbound.cpp | 59 ++++++++++++++++++++++++++++++++------- src/dxvk/dxvk_unbound.h | 24 +++++++++------- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/dxvk/dxvk_unbound.cpp b/src/dxvk/dxvk_unbound.cpp index a06eafe9..fd2af2f3 100644 --- a/src/dxvk/dxvk_unbound.cpp +++ b/src/dxvk/dxvk_unbound.cpp @@ -3,18 +3,57 @@ namespace dxvk { DxvkUnboundResources::DxvkUnboundResources(DxvkDevice* dev) - : m_sampler (createSampler(dev)), - m_buffer (createBuffer(dev)) { - + : m_device(dev) { + } DxvkUnboundResources::~DxvkUnboundResources() { } - - - Rc DxvkUnboundResources::createSampler(DxvkDevice* dev) { + + + VkBuffer DxvkUnboundResources::bufferHandle() { + VkBuffer buffer = m_bufferHandle.load(); + + if (likely(buffer != VK_NULL_HANDLE)) + return buffer; + + std::lock_guard lock(m_mutex); + buffer = m_bufferHandle.load(); + + if (buffer) + return buffer; + + m_buffer = createBuffer(); + buffer = m_buffer->getSliceHandle().handle; + + m_bufferHandle.store(buffer, std::memory_order_release); + return buffer; + } + + + VkSampler DxvkUnboundResources::samplerHandle() { + VkSampler sampler = m_samplerHandle.load(); + + if (likely(sampler != VK_NULL_HANDLE)) + return sampler; + + std::lock_guard lock(m_mutex); + sampler = m_samplerHandle.load(); + + if (sampler) + return sampler; + + m_sampler = createSampler(); + sampler = m_sampler->handle(); + + m_samplerHandle.store(sampler, std::memory_order_release); + return sampler; + } + + + Rc DxvkUnboundResources::createSampler() { DxvkSamplerCreateInfo info; info.minFilter = VK_FILTER_LINEAR; info.magFilter = VK_FILTER_LINEAR; @@ -34,11 +73,11 @@ namespace dxvk { info.usePixelCoord = VK_FALSE; info.nonSeamless = VK_FALSE; - return dev->createSampler(info); + return m_device->createSampler(info); } - Rc DxvkUnboundResources::createBuffer(DxvkDevice* dev) { + Rc DxvkUnboundResources::createBuffer() { DxvkBufferCreateInfo info; info.size = MaxUniformBufferSize; info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT @@ -50,12 +89,12 @@ namespace dxvk { | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT - | dev->getShaderPipelineStages(); + | m_device->getShaderPipelineStages(); info.access = VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; - Rc buffer = dev->createBuffer(info, + Rc buffer = m_device->createBuffer(info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); diff --git a/src/dxvk/dxvk_unbound.h b/src/dxvk/dxvk_unbound.h index 8668f38b..52f17a0d 100644 --- a/src/dxvk/dxvk_unbound.h +++ b/src/dxvk/dxvk_unbound.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "dxvk_buffer.h" #include "dxvk_image.h" #include "dxvk_sampler.h" @@ -30,9 +32,7 @@ namespace dxvk { * and index buffers. * \returns Dummy buffer handle */ - VkBuffer bufferHandle() const { - return m_buffer->getSliceHandle().handle; - } + VkBuffer bufferHandle(); /** * \brief Dummy sampler descriptor @@ -42,18 +42,22 @@ namespace dxvk { * still require different behaviour. * \returns Dummy sampler descriptor */ - VkSampler samplerHandle() const { - return m_sampler->handle(); - } + VkSampler samplerHandle(); private: - Rc m_sampler; - Rc m_buffer; + DxvkDevice* m_device; + + std::atomic m_samplerHandle = { VK_NULL_HANDLE }; + std::atomic m_bufferHandle = { VK_NULL_HANDLE }; + + std::mutex m_mutex; + Rc m_sampler; + Rc m_buffer; - Rc createSampler(DxvkDevice* dev); + Rc createSampler(); - Rc createBuffer(DxvkDevice* dev); + Rc createBuffer(); };