diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index 01766066..552cfcc8 100644 --- a/src/d3d11/d3d11_context_def.cpp +++ b/src/d3d11/d3d11_context_def.cpp @@ -191,45 +191,35 @@ namespace dxvk { if (unlikely(!pResource || !pMappedResource)) return E_INVALIDARG; - D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; - pResource->GetType(&resourceDim); - if (MapType == D3D11_MAP_WRITE_DISCARD) { - D3D11DeferredContextMapEntry entry; - + D3D11_RESOURCE_DIMENSION resourceDim; + pResource->GetType(&resourceDim); + + D3D11_MAPPED_SUBRESOURCE mapInfo; HRESULT status = resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER - ? MapBuffer(pResource, &entry) - : MapImage (pResource, Subresource, &entry); + ? MapBuffer(pResource, &mapInfo) + : MapImage (pResource, Subresource, &mapInfo); if (unlikely(FAILED(status))) { *pMappedResource = D3D11_MAPPED_SUBRESOURCE(); return status; } - // Fill mapped resource structure - pMappedResource->pData = entry.MapPointer; - pMappedResource->RowPitch = entry.RowPitch; - pMappedResource->DepthPitch = entry.DepthPitch; - - // Adding a new map entry actually overrides the - // old one in practice because the lookup function - // scans the array in reverse order - m_mappedResources.push_back(std::move(entry)); + AddMapEntry(pResource, Subresource, resourceDim, mapInfo); + *pMappedResource = mapInfo; return S_OK; } else if (MapType == D3D11_MAP_WRITE_NO_OVERWRITE) { // The resource must be mapped with D3D11_MAP_WRITE_DISCARD // before it can be mapped with D3D11_MAP_WRITE_NO_OVERWRITE. auto entry = FindMapEntry(pResource, Subresource); - if (unlikely(entry == m_mappedResources.rend())) { + if (unlikely(!entry)) { *pMappedResource = D3D11_MAPPED_SUBRESOURCE(); return E_INVALIDARG; } // Return same memory region as earlier - pMappedResource->pData = entry->MapPointer; - pMappedResource->RowPitch = entry->RowPitch; - pMappedResource->DepthPitch = entry->DepthPitch; + *pMappedResource = entry->MapInfo; return S_OK; } else { // Not allowed on deferred contexts @@ -283,7 +273,7 @@ namespace dxvk { HRESULT D3D11DeferredContext::MapBuffer( ID3D11Resource* pResource, - D3D11DeferredContextMapEntry* pMapEntry) { + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { D3D11Buffer* pBuffer = static_cast(pResource); if (unlikely(pBuffer->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) { @@ -291,17 +281,15 @@ namespace dxvk { return E_INVALIDARG; } - pMapEntry->pResource = pResource; - pMapEntry->Subresource = 0; - pMapEntry->RowPitch = pBuffer->Desc()->ByteWidth; - pMapEntry->DepthPitch = pBuffer->Desc()->ByteWidth; + pMappedResource->RowPitch = pBuffer->Desc()->ByteWidth; + pMappedResource->DepthPitch = pBuffer->Desc()->ByteWidth; if (likely(m_csFlags.test(DxvkCsChunkFlag::SingleUse))) { // For resources that cannot be written by the GPU, // we may write to the buffer resource directly and // just swap in the buffer slice as needed. auto bufferSlice = pBuffer->AllocSlice(); - pMapEntry->MapPointer = bufferSlice.mapPtr; + pMappedResource->pData = bufferSlice.mapPtr; EmitCs([ cDstBuffer = pBuffer->GetBuffer(), @@ -313,7 +301,7 @@ namespace dxvk { // For GPU-writable resources, we need a data slice // to perform the update operation at execution time. auto dataSlice = AllocUpdateBufferSlice(pBuffer->Desc()->ByteWidth); - pMapEntry->MapPointer = dataSlice.ptr(); + pMappedResource->pData = dataSlice.ptr(); EmitCs([ cDstBuffer = pBuffer->GetBuffer(), @@ -332,7 +320,7 @@ namespace dxvk { HRESULT D3D11DeferredContext::MapImage( ID3D11Resource* pResource, UINT Subresource, - D3D11DeferredContextMapEntry* pMapEntry) { + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { D3D11CommonTexture* pTexture = GetCommonTexture(pResource); if (unlikely(pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE)) { @@ -354,11 +342,9 @@ namespace dxvk { auto layout = pTexture->GetSubresourceLayout(formatInfo->aspectMask, Subresource); auto dataSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, levelExtent)); - pMapEntry->pResource = pResource; - pMapEntry->Subresource = Subresource; - pMapEntry->RowPitch = layout.RowPitch; - pMapEntry->DepthPitch = layout.DepthPitch; - pMapEntry->MapPointer = dataSlice.mapPtr(0); + pMappedResource->RowPitch = layout.RowPitch; + pMappedResource->DepthPitch = layout.DepthPitch; + pMappedResource->pData = dataSlice.mapPtr(0); UpdateImage(pTexture, &subresource, VkOffset3D { 0, 0, 0 }, levelExtent, @@ -378,18 +364,17 @@ namespace dxvk { if (unlikely(CopyFlags == D3D11_COPY_NO_OVERWRITE)) { auto entry = FindMapEntry(pDstBuffer, 0); - if (entry != m_mappedResources.rend()) - mapPtr = entry->MapPointer; + if (entry) + mapPtr = entry->MapInfo.pData; } if (likely(!mapPtr)) { // The caller validates the map mode, so we can // safely ignore the MapBuffer return value here - D3D11DeferredContextMapEntry entry; - MapBuffer(pDstBuffer, &entry); - - mapPtr = entry.MapPointer; - m_mappedResources.push_back(std::move(entry)); + D3D11_MAPPED_SUBRESOURCE mapInfo; + MapBuffer(pDstBuffer, &mapInfo); + AddMapEntry(pDstBuffer, 0, D3D11_RESOURCE_DIMENSION_BUFFER, mapInfo); + mapPtr = mapInfo.pData; } std::memcpy(reinterpret_cast(mapPtr) + Offset, pSrcData, Length); @@ -437,6 +422,35 @@ namespace dxvk { } + D3D11DeferredContextMapEntry* D3D11DeferredContext::FindMapEntry( + ID3D11Resource* pResource, + UINT Subresource) { + // Recently mapped resources as well as entries with + // up-to-date map infos will be located at the end + // of the resource array, so scan in reverse order. + size_t size = m_mappedResources.size(); + + for (size_t i = 1; i <= size; i++) { + auto entry = &m_mappedResources[size - i]; + + if (entry->Resource.Get() == pResource + && entry->Resource.GetSubresource() == Subresource) + return entry; + } + + return nullptr; + } + + void D3D11DeferredContext::AddMapEntry( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_RESOURCE_DIMENSION ResourceType, + const D3D11_MAPPED_SUBRESOURCE& MapInfo) { + m_mappedResources.emplace_back(pResource, + Subresource, ResourceType, MapInfo); + } + + DxvkCsChunkFlags D3D11DeferredContext::GetCsChunkFlags( D3D11Device* pDevice) { return pDevice->GetOptions()->dcSingleUseMode diff --git a/src/d3d11/d3d11_context_def.h b/src/d3d11/d3d11_context_def.h index 5189571d..c5fe49c9 100644 --- a/src/d3d11/d3d11_context_def.h +++ b/src/d3d11/d3d11_context_def.h @@ -5,17 +5,22 @@ #include "d3d11_context.h" #include "d3d11_texture.h" -#include #include namespace dxvk { struct D3D11DeferredContextMapEntry { - Com pResource; - UINT Subresource; - UINT RowPitch; - UINT DepthPitch; - void* MapPointer; + D3D11DeferredContextMapEntry() { } + D3D11DeferredContextMapEntry( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_RESOURCE_DIMENSION ResourceType, + const D3D11_MAPPED_SUBRESOURCE& MappedResource) + : Resource(pResource, Subresource, ResourceType), + MapInfo(MappedResource) { } + + D3D11ResourceRef Resource; + D3D11_MAPPED_SUBRESOURCE MapInfo; }; class D3D11DeferredContext : public D3D11DeviceContext { @@ -114,12 +119,12 @@ namespace dxvk { HRESULT MapBuffer( ID3D11Resource* pResource, - D3D11DeferredContextMapEntry* pMapEntry); + D3D11_MAPPED_SUBRESOURCE* pMappedResource); HRESULT MapImage( ID3D11Resource* pResource, UINT Subresource, - D3D11DeferredContextMapEntry* pMapEntry); + D3D11_MAPPED_SUBRESOURCE* pMappedResource); void UpdateMappedBuffer( D3D11Buffer* pDstBuffer, @@ -135,23 +140,25 @@ namespace dxvk { void EmitCsChunk(DxvkCsChunkRef&& chunk); void TrackTextureSequenceNumber( - D3D11CommonTexture* pResource, - UINT Subresource); + D3D11CommonTexture* pResource, + UINT Subresource); void TrackBufferSequenceNumber( - D3D11Buffer* pResource); + D3D11Buffer* pResource); + + D3D11DeferredContextMapEntry* FindMapEntry( + ID3D11Resource* pResource, + UINT Subresource); + + void AddMapEntry( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_RESOURCE_DIMENSION ResourceType, + const D3D11_MAPPED_SUBRESOURCE& MapInfo); static DxvkCsChunkFlags GetCsChunkFlags( D3D11Device* pDevice); - auto FindMapEntry(ID3D11Resource* pResource, UINT Subresource) { - return std::find_if(m_mappedResources.rbegin(), m_mappedResources.rend(), - [pResource, Subresource] (const D3D11DeferredContextMapEntry& entry) { - return entry.pResource == pResource - && entry.Subresource == Subresource; - }); - } - }; }