From bdce9a69fbfe89c90e142067ea473de597dea378 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 14 Dec 2017 12:29:41 +0100 Subject: [PATCH] [d3d11] Map() optimization removed, needs buffer renaming The naive optimization to use staging buffers rather than actual mapping turned out to be no more efficient than the previous approach. In order to achieve good performance, buffer renaming must be implemented instead. --- src/d3d11/d3d11_buffer.cpp | 61 ++++++++++++++++++-------------------- src/d3d11/d3d11_buffer.h | 2 -- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index b1fd409f..ec1c670d 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -91,44 +91,41 @@ namespace dxvk { if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) return DXGI_ERROR_WAS_STILL_DRAWING; - if (MapType == D3D11_MAP_WRITE_DISCARD) { - // Instead of synchronizing with the device, which is - // highly inefficient, return a host-local buffer to - // the application and upload its contents on unmap() - // TODO evaluate whether this improves performance - m_mapData = new DxvkDataBuffer(buffer->info().size); - - pMappedSubresource->pData = m_mapData->data(); - pMappedSubresource->RowPitch = buffer->info().size; - pMappedSubresource->DepthPitch = buffer->info().size; - return S_OK; - } else { - // We have to wait for the device to complete - pContext->Flush(); - pContext->Synchronize(); - - pMappedSubresource->pData = buffer->mapPtr(0); - pMappedSubresource->RowPitch = buffer->info().size; - pMappedSubresource->DepthPitch = buffer->info().size; - return S_OK; - } + // TODO optimize this. In order to properly cover common use cases + // like frequent constant buffer updates, we must implement buffer + // renaming techniques. The current approach is inefficient as it + // leads to a lot of Flush() and Synchronize() calls. + // + // Possible solution: + // (1) Create buffers with a significantly larger size if they + // can be mapped by the host for writing. If mapping the + // buffer would stall on D3D11_MAP_WRITE_DISCARD, map the + // next slice. on D3D11_MAP_WRITE_NO_OVERWRITE, return the + // current slice. If the buffer is bound, update bindings. + // (2) If no more slices are available, create a new buffer. + // Limit the number of buffers to a small, fixed number. + // (3) If no more buffers are available, flush and synchronize. + // (4) When renaming the buffer internally, all active bindings + // need to be updated internally as well. + // + // In order to support deferred contexts, the immediate context + // must commit all changes to the initial buffer slice prior to + // executing a command list. When mapping on deferred contexts, + // the deferred context shall create local buffer objects. + pContext->Flush(); + pContext->Synchronize(); + + pMappedSubresource->pData = buffer->mapPtr(0); + pMappedSubresource->RowPitch = buffer->info().size; + pMappedSubresource->DepthPitch = buffer->info().size; + return S_OK; } } void D3D11Buffer::Unmap( D3D11DeviceContext* pContext) { - if (m_mapData != nullptr) { - const Rc context - = pContext->GetDXVKContext(); - - context->updateBuffer( - m_resource->GetDXVKBuffer(), - 0, m_mapData->size(), - m_mapData->data()); - - m_mapData = nullptr; - } + // Nothing to see here, folks } diff --git a/src/d3d11/d3d11_buffer.h b/src/d3d11/d3d11_buffer.h index 0f59284e..9886e2b5 100644 --- a/src/d3d11/d3d11_buffer.h +++ b/src/d3d11/d3d11_buffer.h @@ -55,8 +55,6 @@ namespace dxvk { Com m_resource; D3D11_BUFFER_DESC m_desc; - Rc m_mapData; - }; }