mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 02:52:10 +01:00
[d3d11] Implemented image mapping on deferred contexts
Also refactored buffer mapping to reduce code duplication. Optimized the lookup function for a small performance gain in games which map a lot of resources on deferred contexts.
This commit is contained in:
parent
61c55d6f89
commit
675b1c5b8c
@ -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 (MapType == D3D11_MAP_WRITE_DISCARD) {
|
||||
D3D11DeferredContextMapEntry entry;
|
||||
|
||||
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
|
||||
return MapBuffer(
|
||||
static_cast<D3D11Buffer*>(pResource),
|
||||
MapType, MapFlags, pMappedResource);
|
||||
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<D3D11Buffer*>(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<DxvkBuffer> buffer = pResource->GetBuffer();
|
||||
ID3D11Resource* pResource,
|
||||
D3D11_MAP MapType,
|
||||
UINT MapFlags,
|
||||
D3D11DeferredContextMapEntry* pMapEntry) {
|
||||
const D3D11Buffer* pBuffer = static_cast<D3D11Buffer*>(pResource);
|
||||
const Rc<DxvkBuffer> 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<DxvkImage> 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<D3D11Buffer*>(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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "d3d11_texture.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -65,31 +66,33 @@ namespace dxvk {
|
||||
std::vector<D3D11DeferredContextMapEntry> 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<D3D11CommandList> CreateCommandList();
|
||||
|
||||
void EmitCsChunk(Rc<DxvkCsChunk>&& 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user