From 11b269efd18f1545371240cc9d8e21784e27d1c6 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 16 Oct 2018 12:29:04 +0200 Subject: [PATCH] [d3d11] Save a few CPU cycles in Map/MapBuffer --- src/d3d11/d3d11_buffer.h | 13 ++++--- src/d3d11/d3d11_context_def.cpp | 10 +---- src/d3d11/d3d11_context_imm.cpp | 67 +++++++++++++++++++-------------- 3 files changed, 48 insertions(+), 42 deletions(-) diff --git a/src/d3d11/d3d11_buffer.h b/src/d3d11/d3d11_buffer.h index 40e3a2d1..1782469d 100644 --- a/src/d3d11/d3d11_buffer.h +++ b/src/d3d11/d3d11_buffer.h @@ -58,7 +58,7 @@ namespace dxvk { const D3D11_BUFFER_DESC* Desc() const { return &m_desc; } - + Rc GetBuffer() const { return m_buffer; } @@ -80,17 +80,18 @@ namespace dxvk { } VkDeviceSize GetSize() const { - return m_buffer->info().size; + return m_desc.ByteWidth; + } + + DxvkPhysicalBufferSlice DiscardSlice() { + m_mapped = m_buffer->allocPhysicalSlice(); + return m_mapped; } DxvkPhysicalBufferSlice GetMappedSlice() const { return m_mapped; } - void SetMappedSlice(const DxvkPhysicalBufferSlice& slice) { - m_mapped = slice; - } - D3D10Buffer* GetD3D10Iface() { return &m_d3d10; } diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index e47a7c0d..08923858 100644 --- a/src/d3d11/d3d11_context_def.cpp +++ b/src/d3d11/d3d11_context_def.cpp @@ -159,9 +159,6 @@ namespace dxvk { D3D11Buffer* pBuffer = static_cast(pResource); const Rc buffer = pBuffer->GetBuffer(); - D3D11_BUFFER_DESC bufferDesc; - pBuffer->GetDesc(&bufferDesc); - if (!(buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { Logger::err("D3D11: Cannot map a device-local buffer"); return E_INVALIDARG; @@ -173,7 +170,7 @@ namespace dxvk { pMapEntry->RowPitch = pBuffer->GetSize(); pMapEntry->DepthPitch = pBuffer->GetSize(); - if (bufferDesc.Usage == D3D11_USAGE_DYNAMIC && m_parent->GetOptions()->dcMapSpeedHack) { + if (pBuffer->Desc()->Usage == D3D11_USAGE_DYNAMIC && m_parent->GetOptions()->dcMapSpeedHack) { // For resources that cannot be written by the GPU, // we may write to the buffer resource directly and // just swap in the physical buffer slice as needed. @@ -240,10 +237,7 @@ namespace dxvk { const D3D11DeferredContextMapEntry* pMapEntry) { D3D11Buffer* pBuffer = static_cast(pResource); - D3D11_BUFFER_DESC bufferDesc; - pBuffer->GetDesc(&bufferDesc); - - if (bufferDesc.Usage == D3D11_USAGE_DYNAMIC && m_parent->GetOptions()->dcMapSpeedHack) { + if (pBuffer->Desc()->Usage == D3D11_USAGE_DYNAMIC && m_parent->GetOptions()->dcMapSpeedHack) { EmitCs([ cDstBuffer = pBuffer->GetBuffer(), cPhysSlice = pMapEntry->BufferSlice diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp index e9af28bb..23759414 100644 --- a/src/d3d11/d3d11_context_imm.cpp +++ b/src/d3d11/d3d11_context_imm.cpp @@ -157,28 +157,32 @@ namespace dxvk { D3D11_MAP MapType, UINT MapFlags, D3D11_MAPPED_SUBRESOURCE* pMappedResource) { - if (pResource == nullptr) - return DXGI_ERROR_INVALID_CALL; - - if (pMappedResource != nullptr) { - pMappedResource->pData = nullptr; - pMappedResource->RowPitch = 0; - pMappedResource->DepthPitch = 0; - } + if (!pResource || !pMappedResource) + return E_INVALIDARG; D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; pResource->GetType(&resourceDim); + + HRESULT hr; if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { - return MapBuffer( + hr = MapBuffer( static_cast(pResource), MapType, MapFlags, pMappedResource); } else { - return MapImage( + hr = MapImage( GetCommonTexture(pResource), Subresource, MapType, MapFlags, pMappedResource); } + + if (FAILED(hr)) { + pMappedResource->pData = nullptr; + pMappedResource->RowPitch = 0; + pMappedResource->DepthPitch = 0; + } + + return hr; } @@ -328,7 +332,7 @@ namespace dxvk { UINT MapFlags, D3D11_MAPPED_SUBRESOURCE* pMappedResource) { Rc buffer = pResource->GetBuffer(); - + if (!(buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { Logger::err("D3D11: Cannot map a device-local buffer"); return E_INVALIDARG; @@ -338,29 +342,36 @@ namespace dxvk { // Allocate a new backing slice for the buffer and set // it as the 'new' mapped slice. This assumes that the // only way to invalidate a buffer is by mapping it. - auto physicalSlice = buffer->allocPhysicalSlice(); - pResource->SetMappedSlice(physicalSlice); + auto physicalSlice = pResource->DiscardSlice(); + pMappedResource->pData = physicalSlice.mapPtr(0); + pMappedResource->RowPitch = pResource->GetSize(); + pMappedResource->DepthPitch = pResource->GetSize(); EmitCs([ - cBuffer = buffer, - cPhysicalSlice = physicalSlice + cBuffer = std::move(buffer), + cPhysicalSlice = std::move(physicalSlice) ] (DxvkContext* ctx) { ctx->invalidateBuffer(cBuffer, cPhysicalSlice); }); - } else if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) { - if (!WaitForResource(buffer->resource(), MapFlags)) - return DXGI_ERROR_WAS_STILL_DRAWING; + + return S_OK; + } else { + // Wait until the resource is no longer in use + if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) { + if (!WaitForResource(buffer->resource(), MapFlags)) + return DXGI_ERROR_WAS_STILL_DRAWING; + } + + // Use map pointer from previous map operation. This + // way we don't have to synchronize with the CS thread + // if the map mode is D3D11_MAP_WRITE_NO_OVERWRITE. + DxvkPhysicalBufferSlice physicalSlice = pResource->GetMappedSlice(); + + pMappedResource->pData = physicalSlice.mapPtr(0); + pMappedResource->RowPitch = pResource->GetSize(); + pMappedResource->DepthPitch = pResource->GetSize(); + return S_OK; } - - // Use map pointer from previous map operation. This - // way we don't have to synchronize with the CS thread - // if the map mode is D3D11_MAP_WRITE_NO_OVERWRITE. - DxvkPhysicalBufferSlice physicalSlice = pResource->GetMappedSlice(); - - pMappedResource->pData = physicalSlice.mapPtr(0); - pMappedResource->RowPitch = pResource->GetSize(); - pMappedResource->DepthPitch = pResource->GetSize(); - return S_OK; }