From f1c3b59e87746f56f1956bfa54b9403d0e5317b1 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 19 Mar 2018 03:19:13 +0100 Subject: [PATCH] [d3d11] Implemented buffer mapping on deferred contexts Allows the MultiThreadedRendering demo from the Microsoft SDK to run. --- src/d3d11/d3d11_buffer.h | 8 +-- src/d3d11/d3d11_context_def.cpp | 122 +++++++++++++++++++++++++++++++- src/d3d11/d3d11_context_def.h | 45 ++++++++++++ src/d3d11/d3d11_context_imm.cpp | 2 +- 4 files changed, 169 insertions(+), 8 deletions(-) diff --git a/src/d3d11/d3d11_buffer.h b/src/d3d11/d3d11_buffer.h index 5e8b7d54..c13067ca 100644 --- a/src/d3d11/d3d11_buffer.h +++ b/src/d3d11/d3d11_buffer.h @@ -48,10 +48,10 @@ namespace dxvk { void STDMETHODCALLTYPE GetDesc( D3D11_BUFFER_DESC *pDesc) final; - /** - * \brief Retrieves buffer slice - * \returns Buffer slice containing the entire buffer - */ + Rc GetBuffer() const { + return m_buffer; + } + DxvkBufferSlice GetBufferSlice() const { return DxvkBufferSlice(m_buffer, 0, m_buffer->info().size); } diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index 426167f5..924a2d17 100644 --- a/src/d3d11/d3d11_context_def.cpp +++ b/src/d3d11/d3d11_context_def.cpp @@ -56,6 +56,7 @@ namespace dxvk { else ClearState(); + m_mappedResources.clear(); return S_OK; } @@ -66,15 +67,130 @@ namespace dxvk { D3D11_MAP MapType, UINT MapFlags, D3D11_MAPPED_SUBRESOURCE* pMappedResource) { - Logger::err("D3D11DeferredContext::Map: Not implemented"); - return E_NOTIMPL; + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + if (MapType != D3D11_MAP_WRITE_DISCARD + && MapType != D3D11_MAP_WRITE_NO_OVERWRITE) + return E_INVALIDARG; + + if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { + return MapBuffer( + static_cast(pResource), + MapType, MapFlags, pMappedResource); + } else { + return MapImage( + GetCommonTexture(pResource), + Subresource, MapType, MapFlags, + pMappedResource); + } } void STDMETHODCALLTYPE D3D11DeferredContext::Unmap( ID3D11Resource* pResource, UINT Subresource) { - Logger::err("D3D11DeferredContext::Unmap: Not implemented"); + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { + UnmapBuffer(static_cast(pResource)); + } else { + UnmapImage( + GetCommonTexture(pResource), + Subresource); + } + } + + + HRESULT D3D11DeferredContext::MapBuffer( + D3D11Buffer* pResource, + D3D11_MAP MapType, + 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; + } + + if (pMappedResource == nullptr) + return S_FALSE; + + auto entry = FindMapEntry(pResource, 0); + + if (MapType == D3D11_MAP_WRITE_DISCARD) { + if (entry != m_mappedResources.end()) + m_mappedResources.erase(entry); + + D3D11DeferredContextMapEntry mapEntry; + mapEntry.pResource = pResource; + mapEntry.Subresource = 0; + mapEntry.MapType = D3D11_MAP_WRITE_DISCARD; + mapEntry.RowPitch = pResource->GetSize(); + mapEntry.DepthPitch = pResource->GetSize(); + mapEntry.DataSlice = AllocUpdateBufferSlice(pResource->GetSize()); + m_mappedResources.push_back(mapEntry); + + pMappedResource->pData = mapEntry.DataSlice.ptr(); + pMappedResource->RowPitch = mapEntry.RowPitch; + pMappedResource->DepthPitch = mapEntry.DepthPitch; + return S_OK; + } else { + // The resource must be mapped with D3D11_MAP_WRITE_DISCARD + // before it can be mapped with D3D11_MAP_WRITE_NO_OVERWRITE. + if (entry == m_mappedResources.end()) + return E_INVALIDARG; + + // Return same memory region as earlier + entry->MapType = D3D11_MAP_WRITE_NO_OVERWRITE; + + pMappedResource->pData = entry->DataSlice.ptr(); + pMappedResource->RowPitch = entry->RowPitch; + pMappedResource->DepthPitch = entry->DepthPitch; + return S_OK; + } + } + + + HRESULT D3D11DeferredContext::MapImage( + D3D11CommonTexture* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + Logger::err("D3D11DeferredContext::MapImage: Not implemented"); + return E_NOTIMPL; + } + + + void D3D11DeferredContext::UnmapBuffer( + D3D11Buffer* pResource) { + auto entry = FindMapEntry(pResource, 0); + + if (entry == m_mappedResources.end()) { + Logger::err("D3D11DeferredContext::Unmap: Buffer not mapped"); + return; + } + + if (entry->MapType == D3D11_MAP_WRITE_DISCARD) { + EmitCs([ + cDstBuffer = pResource->GetBuffer(), + cDataSlice = entry->DataSlice + ] (DxvkContext* ctx) { + DxvkPhysicalBufferSlice slice = cDstBuffer->allocPhysicalSlice(); + std::memcpy(slice.mapPtr(0), cDataSlice.ptr(), cDataSlice.length()); + ctx->invalidateBuffer(cDstBuffer, slice); + }); + } + } + + + void D3D11DeferredContext::UnmapImage( + D3D11CommonTexture* pResource, + UINT Subresource) { + Logger::err("D3D11DeferredContext::UnmapImage: Not implemented"); } diff --git a/src/d3d11/d3d11_context_def.h b/src/d3d11/d3d11_context_def.h index f04fd2db..2250f927 100644 --- a/src/d3d11/d3d11_context_def.h +++ b/src/d3d11/d3d11_context_def.h @@ -1,10 +1,21 @@ #pragma once +#include "d3d11_buffer.h" #include "d3d11_cmdlist.h" #include "d3d11_context.h" +#include "d3d11_texture.h" namespace dxvk { + struct D3D11DeferredContextMapEntry { + Com pResource; + UINT Subresource; + D3D11_MAP MapType; + UINT RowPitch; + UINT DepthPitch; + DxvkDataSlice DataSlice; + }; + class D3D11DeferredContext : public D3D11DeviceContext { public: @@ -43,12 +54,46 @@ namespace dxvk { const UINT m_contextFlags; + // Command list that we're recording Com m_commandList; + // Info about currently mapped (sub)resources. Using a vector + // here is reasonable since there will usually only be a small + // number of mapped resources per command list. + std::vector m_mappedResources; + + HRESULT MapBuffer( + D3D11Buffer* pResource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource); + + HRESULT MapImage( + D3D11CommonTexture* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource); + + void UnmapBuffer( + D3D11Buffer* pResource); + + void UnmapImage( + D3D11CommonTexture* pResource, + UINT Subresource); + Com CreateCommandList(); void EmitCsChunk(Rc&& chunk) final; + auto FindMapEntry(ID3D11Resource* pResource, UINT Subresource) { + return std::find_if(m_mappedResources.begin(), m_mappedResources.end(), + [pResource, Subresource] (const D3D11DeferredContextMapEntry& entry) { + return entry.pResource == pResource + && entry.Subresource == Subresource; + }); + } + }; } \ No newline at end of file diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp index 19e09c1a..d4174918 100644 --- a/src/d3d11/d3d11_context_imm.cpp +++ b/src/d3d11/d3d11_context_imm.cpp @@ -128,7 +128,7 @@ namespace dxvk { D3D11_MAP MapType, UINT MapFlags, D3D11_MAPPED_SUBRESOURCE* pMappedResource) { - Rc buffer = pResource->GetBufferSlice().buffer(); + Rc buffer = pResource->GetBuffer(); if (!(buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { Logger::err("D3D11: Cannot map a device-local buffer");