diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index 786dcf2e9..541aa7434 100644 --- a/src/d3d11/d3d11_context_def.cpp +++ b/src/d3d11/d3d11_context_def.cpp @@ -76,19 +76,44 @@ namespace dxvk { pMappedResource->DepthPitch = 0; } - 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); + if (MapType == D3D11_MAP_WRITE_DISCARD) { + D3D11DeferredContextMapEntry entry; + + HRESULT status = resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER + ? MapBuffer(pResource, MapType, MapFlags, &entry) + : MapImage (pResource, Subresource, MapType, MapFlags, &entry); + + if (FAILED(status)) + return status; + + // 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(entry); + + // Fill mapped resource structure + pMappedResource->pData = entry.DataSlice.ptr(); + pMappedResource->RowPitch = entry.RowPitch; + pMappedResource->DepthPitch = entry.DepthPitch; + 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 (entry == m_mappedResources.rend()) + 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; } else { - return MapImage( - GetCommonTexture(pResource), - Subresource, MapType, MapFlags, - pMappedResource); + // Not allowed on deferred contexts + return E_INVALIDARG; } } @@ -99,101 +124,129 @@ namespace dxvk { 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); + auto entry = FindMapEntry(pResource, Subresource); + + if (entry == m_mappedResources.rend()) { + Logger::err("D3D11DeferredContext::Unmap: Subresource not mapped"); + return; + } + + if (entry->MapType == D3D11_MAP_WRITE_DISCARD) { + if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) + UnmapBuffer(pResource, &(*entry)); + else + UnmapImage(pResource, Subresource, &(*entry)); } } HRESULT D3D11DeferredContext::MapBuffer( - D3D11Buffer* pResource, - D3D11_MAP MapType, - UINT MapFlags, - D3D11_MAPPED_SUBRESOURCE* pMappedResource) { - Rc buffer = pResource->GetBuffer(); + ID3D11Resource* pResource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11DeferredContextMapEntry* pMapEntry) { + const D3D11Buffer* pBuffer = static_cast(pResource); + const Rc buffer = pBuffer->GetBuffer(); if (!(buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { Logger::err("D3D11: Cannot map a device-local buffer"); return E_INVALIDARG; } - 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; - } + pMapEntry->pResource = pResource; + pMapEntry->Subresource = 0; + pMapEntry->MapType = D3D11_MAP_WRITE_DISCARD; + pMapEntry->RowPitch = pBuffer->GetSize(); + pMapEntry->DepthPitch = pBuffer->GetSize(); + pMapEntry->DataSlice = AllocUpdateBufferSlice(pBuffer->GetSize()); + 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; + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11DeferredContextMapEntry* pMapEntry) { + const D3D11CommonTexture* pTexture = GetCommonTexture(pResource); + const Rc image = pTexture->GetImage(); + + if (pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE) { + Logger::err("D3D11: Cannot map a device-local image"); + return E_INVALIDARG; + } + + const DxvkFormatInfo* formatInfo = imageFormatInfo(image->info().format); + + VkImageSubresource subresource = + pTexture->GetSubresourceFromIndex( + VK_IMAGE_ASPECT_COLOR_BIT, Subresource); + + VkExtent3D levelExtent = image->mipLevelExtent(subresource.mipLevel); + VkExtent3D blockCount = util::computeBlockCount( + levelExtent, formatInfo->blockSize); + + VkDeviceSize eSize = formatInfo->elementSize; + VkDeviceSize xSize = blockCount.width * eSize; + VkDeviceSize ySize = blockCount.height * xSize; + VkDeviceSize zSize = blockCount.depth * ySize; + + pMapEntry->pResource = pResource; + pMapEntry->Subresource = Subresource; + pMapEntry->MapType = D3D11_MAP_WRITE_DISCARD; + pMapEntry->RowPitch = xSize; + pMapEntry->DepthPitch = ySize; + pMapEntry->DataSlice = AllocUpdateBufferSlice(zSize); + return S_OK; } void D3D11DeferredContext::UnmapBuffer( - D3D11Buffer* pResource) { - auto entry = FindMapEntry(pResource, 0); + ID3D11Resource* pResource, + const D3D11DeferredContextMapEntry* pMapEntry) { + D3D11Buffer* pBuffer = static_cast(pResource); - 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); - }); - } + 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); + }); } void D3D11DeferredContext::UnmapImage( - D3D11CommonTexture* pResource, - UINT Subresource) { - Logger::err("D3D11DeferredContext::UnmapImage: Not implemented"); + ID3D11Resource* pResource, + UINT Subresource, + const D3D11DeferredContextMapEntry* pMapEntry) { + // TODO If the texture itself is mapped to host-visible + // memory, write the data slice directly to the image. + const D3D11CommonTexture* pTexture = GetCommonTexture(pResource); + + EmitCs([ + cImage = pTexture->GetImage(), + cSubresource = pTexture->GetSubresourceFromIndex( + VK_IMAGE_ASPECT_COLOR_BIT, Subresource), + cDataSlice = pMapEntry->DataSlice, + cDataPitchPerRow = pMapEntry->RowPitch, + cDataPitchPerLayer = pMapEntry->DepthPitch + ] (DxvkContext* ctx) { + VkImageSubresourceLayers srLayers; + srLayers.aspectMask = cSubresource.aspectMask; + srLayers.mipLevel = cSubresource.mipLevel; + srLayers.baseArrayLayer = cSubresource.arrayLayer; + srLayers.layerCount = 1; + + ctx->updateImage( + cImage, srLayers, VkOffset3D { 0, 0, 0 }, + cImage->mipLevelExtent(cSubresource.mipLevel), + cDataSlice.ptr(), + cDataPitchPerRow, + cDataPitchPerLayer); + }); } diff --git a/src/d3d11/d3d11_context_def.h b/src/d3d11/d3d11_context_def.h index f3f2d7034..d0ea7bc6f 100644 --- a/src/d3d11/d3d11_context_def.h +++ b/src/d3d11/d3d11_context_def.h @@ -6,6 +6,7 @@ #include "d3d11_texture.h" #include +#include namespace dxvk { @@ -65,31 +66,33 @@ namespace dxvk { std::vector m_mappedResources; HRESULT MapBuffer( - D3D11Buffer* pResource, - D3D11_MAP MapType, - UINT MapFlags, - D3D11_MAPPED_SUBRESOURCE* pMappedResource); + ID3D11Resource* pResource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11DeferredContextMapEntry* pMapEntry); HRESULT MapImage( - D3D11CommonTexture* pResource, - UINT Subresource, - D3D11_MAP MapType, - UINT MapFlags, - D3D11_MAPPED_SUBRESOURCE* pMappedResource); + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11DeferredContextMapEntry* pMapEntry); void UnmapBuffer( - D3D11Buffer* pResource); + ID3D11Resource* pResource, + const D3D11DeferredContextMapEntry* pMapEntry); void UnmapImage( - D3D11CommonTexture* pResource, - UINT Subresource); + ID3D11Resource* pResource, + UINT Subresource, + const D3D11DeferredContextMapEntry* pMapEntry); Com CreateCommandList(); void EmitCsChunk(Rc&& chunk) final; auto FindMapEntry(ID3D11Resource* pResource, UINT Subresource) { - return std::find_if(m_mappedResources.begin(), m_mappedResources.end(), + return std::find_if(m_mappedResources.rbegin(), m_mappedResources.rend(), [pResource, Subresource] (const D3D11DeferredContextMapEntry& entry) { return entry.pResource == pResource && entry.Subresource == Subresource;