From 9acc4a1a82765af872560314c89f8f6538f13aaf Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 18 Jan 2018 11:55:27 +0100 Subject: [PATCH] [d3d11] Map default constant buffers to host memory Improves performance in applications that use UpdateSubresources to frequently update constant buffers, such as Unigine Heaven, Unigine Valley and Homefront. --- src/d3d11/d3d11_buffer.cpp | 18 +++++++++++++++++- src/d3d11/d3d11_buffer.h | 3 +++ src/d3d11/d3d11_context.cpp | 11 +++++++++-- src/dxvk/dxvk_buffer.h | 17 +++++++++++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index e0809ddee..a81214429 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -120,7 +120,23 @@ namespace dxvk { } return m_device->GetDXVKDevice()->createBuffer( - info, GetMemoryFlagsForUsage(pDesc->Usage)); + info, GetMemoryFlags(pDesc)); + } + + + VkMemoryPropertyFlags D3D11Buffer::GetMemoryFlags( + const D3D11_BUFFER_DESC* pDesc) const { + // Default constant buffers may get updated frequently with calls + // to D3D11DeviceContext::UpdateSubresource, so we'll map them to + // host memory in order to allow direct access to the buffer + if ((pDesc->Usage == D3D11_USAGE_DEFAULT) + && (pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER)) { + return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + } + + // Use default memory flags for the intended use + return GetMemoryFlagsForUsage(pDesc->Usage); } } diff --git a/src/d3d11/d3d11_buffer.h b/src/d3d11/d3d11_buffer.h index 0059f15cb..07da62bad 100644 --- a/src/d3d11/d3d11_buffer.h +++ b/src/d3d11/d3d11_buffer.h @@ -59,6 +59,9 @@ namespace dxvk { Rc CreateBuffer( const D3D11_BUFFER_DESC* pDesc) const; + VkMemoryPropertyFlags GetMemoryFlags( + const D3D11_BUFFER_DESC* pDesc) const; + }; } diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index b7588c595..3636db34e 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -213,7 +213,7 @@ namespace dxvk { const D3D11Buffer* resource = static_cast(pResource); const Rc buffer = resource->GetBufferSlice().buffer(); - if (buffer->mapPtr(0) == nullptr) { + if (!(buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { Logger::err("D3D11: Cannot map a device-local buffer"); return E_INVALIDARG; } @@ -680,7 +680,14 @@ namespace dxvk { return; } - if (size != 0) { + if (size == 0) + return; + + if (((size == bufferSlice.length()) + && (bufferSlice.memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))) { + m_context->invalidateBuffer(bufferSlice.buffer()); + std::memcpy(bufferSlice.mapPtr(0), pSrcData, size); + } else { m_context->updateBuffer( bufferSlice.buffer(), bufferSlice.offset() + offset, diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index a9e8f7710..d18175c78 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -102,6 +102,17 @@ namespace dxvk { return m_info; } + /** + * \brief Memory type flags + * + * Use this to determine whether a + * buffer is mapped to host memory. + * \returns Vulkan memory flags + */ + VkMemoryPropertyFlags memFlags() const { + return m_memFlags; + } + /** * \brief Buffer handle * \returns Buffer handle @@ -260,6 +271,12 @@ namespace dxvk { return m_buffer->resource(); } + VkMemoryPropertyFlags memFlags() const { + return m_buffer != nullptr + ? m_buffer->memFlags() + : 0; + } + VkBuffer handle() const { return m_buffer != nullptr ? m_buffer->handle()