diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index 2aecbcb6c..5acb5db25 100644 --- a/src/d3d11/d3d11_context_def.cpp +++ b/src/d3d11/d3d11_context_def.cpp @@ -92,7 +92,7 @@ namespace dxvk { m_mappedResources.push_back(entry); // Fill mapped resource structure - pMappedResource->pData = entry.DataSlice.ptr(); + pMappedResource->pData = entry.MapPointer; pMappedResource->RowPitch = entry.RowPitch; pMappedResource->DepthPitch = entry.DepthPitch; return S_OK; @@ -107,7 +107,7 @@ namespace dxvk { // Return same memory region as earlier entry->MapType = D3D11_MAP_WRITE_NO_OVERWRITE; - pMappedResource->pData = entry->DataSlice.ptr(); + pMappedResource->pData = entry->MapPointer; pMappedResource->RowPitch = entry->RowPitch; pMappedResource->DepthPitch = entry->DepthPitch; return S_OK; @@ -145,9 +145,12 @@ namespace dxvk { D3D11_MAP MapType, UINT MapFlags, D3D11DeferredContextMapEntry* pMapEntry) { - const D3D11Buffer* pBuffer = static_cast(pResource); + 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; @@ -158,7 +161,20 @@ namespace dxvk { pMapEntry->MapType = D3D11_MAP_WRITE_DISCARD; pMapEntry->RowPitch = pBuffer->GetSize(); pMapEntry->DepthPitch = pBuffer->GetSize(); - pMapEntry->DataSlice = AllocUpdateBufferSlice(pBuffer->GetSize()); + + if (bufferDesc.Usage == D3D11_USAGE_DYNAMIC) { + // 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. + pMapEntry->BufferSlice = buffer->allocPhysicalSlice(); + pMapEntry->MapPointer = pMapEntry->BufferSlice.mapPtr(0); + } else { + // For GPU-writable resources, we need a data slice + // to perform the update operation at execution time. + pMapEntry->DataSlice = AllocUpdateBufferSlice(pBuffer->GetSize()); + pMapEntry->MapPointer = pMapEntry->DataSlice.ptr(); + } + return S_OK; } @@ -203,6 +219,7 @@ namespace dxvk { pMapEntry->RowPitch = xSize; pMapEntry->DepthPitch = ySize; pMapEntry->DataSlice = AllocUpdateBufferSlice(zSize); + pMapEntry->MapPointer = pMapEntry->DataSlice.ptr(); return S_OK; } @@ -212,14 +229,26 @@ namespace dxvk { const D3D11DeferredContextMapEntry* pMapEntry) { D3D11Buffer* pBuffer = static_cast(pResource); - EmitCs([ - cDstBuffer = pBuffer->GetBuffer(), - cDataSlice = pMapEntry->DataSlice - ] (DxvkContext* ctx) { - DxvkPhysicalBufferSlice slice = cDstBuffer->allocPhysicalSlice(); - std::memcpy(slice.mapPtr(0), cDataSlice.ptr(), cDataSlice.length()); - ctx->invalidateBuffer(cDstBuffer, slice); - }); + D3D11_BUFFER_DESC bufferDesc; + pBuffer->GetDesc(&bufferDesc); + + if (bufferDesc.Usage == D3D11_USAGE_DYNAMIC) { + EmitCs([ + cDstBuffer = pBuffer->GetBuffer(), + cPhysSlice = pMapEntry->BufferSlice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cDstBuffer, cPhysSlice); + }); + } else { + EmitCs([ + cDstBuffer = pBuffer->GetBuffer(), + cDataSlice = pMapEntry->DataSlice + ] (DxvkContext* ctx) { + DxvkPhysicalBufferSlice slice = cDstBuffer->allocPhysicalSlice(); + std::memcpy(slice.mapPtr(0), cDataSlice.ptr(), cDataSlice.length()); + ctx->invalidateBuffer(cDstBuffer, slice); + }); + } } diff --git a/src/d3d11/d3d11_context_def.h b/src/d3d11/d3d11_context_def.h index 9821b045e..bf2fc6d57 100644 --- a/src/d3d11/d3d11_context_def.h +++ b/src/d3d11/d3d11_context_def.h @@ -11,12 +11,14 @@ namespace dxvk { struct D3D11DeferredContextMapEntry { - Com pResource; - UINT Subresource; - D3D11_MAP MapType; - UINT RowPitch; - UINT DepthPitch; - DxvkDataSlice DataSlice; + Com pResource; + UINT Subresource; + D3D11_MAP MapType; + UINT RowPitch; + UINT DepthPitch; + DxvkDataSlice DataSlice; + DxvkPhysicalBufferSlice BufferSlice; + void* MapPointer; }; class D3D11DeferredContext : public D3D11DeviceContext {