mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 23:52:10 +01:00
[d3d11] Cache subresource layouts for mapped images
Also adjust the way we expose certain direct-mapped images in order to be as consistent with staging buffer behaviour as possible.
This commit is contained in:
parent
a5e8a42288
commit
c5d776c3b8
@ -193,7 +193,13 @@ namespace dxvk {
|
|||||||
if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
|
if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
|
||||||
m_buffers.push_back(CreateMappedBuffer(j));
|
m_buffers.push_back(CreateMappedBuffer(j));
|
||||||
|
|
||||||
m_mapInfo.push_back({ D3D11_MAP(~0u), 0ull });
|
VkImageSubresource subresource = { };
|
||||||
|
subresource.aspectMask = formatProperties->aspectMask;
|
||||||
|
subresource.arrayLayer = i;
|
||||||
|
subresource.mipLevel = j;
|
||||||
|
|
||||||
|
auto& mapInfo = m_mapInfo.emplace_back();
|
||||||
|
mapInfo.layout = DetermineSubresourceLayout(&imageInfo, subresource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,73 +278,24 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkImageSubresource D3D11CommonTexture::GetSubresourceFromIndex(
|
|
||||||
VkImageAspectFlags Aspect,
|
|
||||||
UINT Subresource) const {
|
|
||||||
VkImageSubresource result;
|
|
||||||
result.aspectMask = Aspect;
|
|
||||||
result.mipLevel = Subresource % m_desc.MipLevels;
|
|
||||||
result.arrayLayer = Subresource / m_desc.MipLevels;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT D3D11CommonTexture::GetSubresourceLayout(
|
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT D3D11CommonTexture::GetSubresourceLayout(
|
||||||
VkImageAspectFlags AspectMask,
|
VkImageAspectFlags AspectMask,
|
||||||
UINT Subresource) const {
|
UINT Subresource) const {
|
||||||
|
// Color is mapped directly and depth-stencil are interleaved
|
||||||
|
// in packed formats, so just use the cached subresource layout
|
||||||
|
constexpr VkImageAspectFlags PlaneAspects = VK_IMAGE_ASPECT_PLANE_0_BIT
|
||||||
|
| VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT;
|
||||||
|
|
||||||
|
if ((Subresource < m_mapInfo.size()) && !(AspectMask & PlaneAspects))
|
||||||
|
return m_mapInfo[Subresource].layout;
|
||||||
|
|
||||||
|
// Safe-guard against invalid subresource index
|
||||||
|
if (Subresource >= m_desc.ArraySize * m_desc.MipLevels)
|
||||||
|
return D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT();
|
||||||
|
|
||||||
|
// Image info is only needed for direct-mapped images
|
||||||
VkImageSubresource subresource = GetSubresourceFromIndex(AspectMask, Subresource);
|
VkImageSubresource subresource = GetSubresourceFromIndex(AspectMask, Subresource);
|
||||||
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = { };
|
return DetermineSubresourceLayout(nullptr, subresource);
|
||||||
|
|
||||||
switch (m_mapMode) {
|
|
||||||
case D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT: {
|
|
||||||
auto vkLayout = m_image->querySubresourceLayout(subresource);
|
|
||||||
layout.Offset = vkLayout.offset;
|
|
||||||
layout.Size = vkLayout.size;
|
|
||||||
layout.RowPitch = vkLayout.rowPitch;
|
|
||||||
layout.DepthPitch = vkLayout.depthPitch;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case D3D11_COMMON_TEXTURE_MAP_MODE_NONE:
|
|
||||||
case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER:
|
|
||||||
case D3D11_COMMON_TEXTURE_MAP_MODE_STAGING: {
|
|
||||||
auto packedFormatInfo = lookupFormatInfo(m_packedFormat);
|
|
||||||
|
|
||||||
VkImageAspectFlags aspects = packedFormatInfo->aspectMask;
|
|
||||||
VkExtent3D mipExtent = MipLevelExtent(subresource.mipLevel);
|
|
||||||
|
|
||||||
while (aspects) {
|
|
||||||
auto aspect = vk::getNextAspect(aspects);
|
|
||||||
auto extent = mipExtent;
|
|
||||||
auto elementSize = packedFormatInfo->elementSize;
|
|
||||||
|
|
||||||
if (packedFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
|
|
||||||
auto plane = &packedFormatInfo->planes[vk::getPlaneIndex(aspect)];
|
|
||||||
extent.width /= plane->blockSize.width;
|
|
||||||
extent.height /= plane->blockSize.height;
|
|
||||||
elementSize = plane->elementSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto blockCount = util::computeBlockCount(extent, packedFormatInfo->blockSize);
|
|
||||||
|
|
||||||
if (!layout.RowPitch) {
|
|
||||||
layout.RowPitch = elementSize * blockCount.width;
|
|
||||||
layout.DepthPitch = elementSize * blockCount.width * blockCount.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDeviceSize size = elementSize * blockCount.width * blockCount.height * blockCount.depth;
|
|
||||||
|
|
||||||
if (aspect & AspectMask)
|
|
||||||
layout.Size += size;
|
|
||||||
else if (!layout.Size)
|
|
||||||
layout.Offset += size;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// D3D wants us to return the total subresource size in some instances
|
|
||||||
if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE2D) layout.RowPitch = layout.Size;
|
|
||||||
if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE3D) layout.DepthPitch = layout.Size;
|
|
||||||
return layout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -591,6 +548,11 @@ namespace dxvk {
|
|||||||
if (!m_desc.BindFlags && m_desc.Usage != D3D11_USAGE_DEFAULT)
|
if (!m_desc.BindFlags && m_desc.Usage != D3D11_USAGE_DEFAULT)
|
||||||
return D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
|
return D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
|
||||||
|
|
||||||
|
// If the packed format and image format don't match, we need to use
|
||||||
|
// a staging buffer and perform format conversion when mapping.
|
||||||
|
if (m_packedFormat != pImageInfo->format)
|
||||||
|
return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
|
||||||
|
|
||||||
// Multi-plane and depth-stencil images have a special memory layout
|
// Multi-plane and depth-stencil images have a special memory layout
|
||||||
// in D3D11, so we can't expose those directly to the app
|
// in D3D11, so we can't expose those directly to the app
|
||||||
auto formatInfo = lookupFormatInfo(pImageInfo->format);
|
auto formatInfo = lookupFormatInfo(pImageInfo->format);
|
||||||
@ -662,6 +624,76 @@ namespace dxvk {
|
|||||||
// tables in some games, which will benefit from faster GPU access.
|
// tables in some games, which will benefit from faster GPU access.
|
||||||
return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
|
return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT D3D11CommonTexture::DetermineSubresourceLayout(
|
||||||
|
const DxvkImageCreateInfo* pImageInfo,
|
||||||
|
const VkImageSubresource& subresource) const {
|
||||||
|
auto formatInfo = lookupFormatInfo(m_packedFormat);
|
||||||
|
|
||||||
|
if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
|
||||||
|
VkSubresourceLayout vkLayout = m_device->GetDXVKDevice()->queryImageSubresourceLayout(*pImageInfo, subresource);
|
||||||
|
|
||||||
|
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT result = { };
|
||||||
|
result.Offset = vkLayout.offset;
|
||||||
|
result.RowPitch = vkLayout.rowPitch;
|
||||||
|
result.DepthPitch = vkLayout.depthPitch;
|
||||||
|
|
||||||
|
// We will only ever use direct mapping for single-aspect images,
|
||||||
|
// so ignore any sort of multi-plane shenanigans on this path
|
||||||
|
auto mipExtent = MipLevelExtent(subresource.mipLevel);
|
||||||
|
auto blockCount = util::computeBlockCount(mipExtent, formatInfo->blockSize);
|
||||||
|
|
||||||
|
// If the image dimensions support it, try to look as close to a
|
||||||
|
// linear buffer as we can. Some games use the depth pitch as a
|
||||||
|
// subresource size and will crash if it includes any padding.
|
||||||
|
if (blockCount.depth == 1u) {
|
||||||
|
if (blockCount.height == 1u) {
|
||||||
|
result.RowPitch = formatInfo->elementSize * blockCount.width;
|
||||||
|
result.DepthPitch = result.RowPitch;
|
||||||
|
} else {
|
||||||
|
result.DepthPitch = vkLayout.rowPitch * blockCount.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Size = blockCount.depth * result.DepthPitch;
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT result = { };
|
||||||
|
|
||||||
|
VkImageAspectFlags aspects = formatInfo->aspectMask;
|
||||||
|
VkExtent3D mipExtent = MipLevelExtent(subresource.mipLevel);
|
||||||
|
|
||||||
|
while (aspects) {
|
||||||
|
auto aspect = vk::getNextAspect(aspects);
|
||||||
|
auto extent = mipExtent;
|
||||||
|
auto elementSize = formatInfo->elementSize;
|
||||||
|
|
||||||
|
if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
|
||||||
|
auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)];
|
||||||
|
extent.width /= plane->blockSize.width;
|
||||||
|
extent.height /= plane->blockSize.height;
|
||||||
|
elementSize = plane->elementSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto blockCount = util::computeBlockCount(extent, formatInfo->blockSize);
|
||||||
|
|
||||||
|
if (!result.RowPitch) {
|
||||||
|
result.RowPitch = elementSize * blockCount.width;
|
||||||
|
result.DepthPitch = elementSize * blockCount.width * blockCount.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceSize size = elementSize * blockCount.width * blockCount.height * blockCount.depth;
|
||||||
|
|
||||||
|
if (aspect & subresource.aspectMask)
|
||||||
|
result.Size += size;
|
||||||
|
else if (!result.Size)
|
||||||
|
result.Offset += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11CommonTexture::ExportImageInfo() {
|
void D3D11CommonTexture::ExportImageInfo() {
|
||||||
@ -709,9 +741,13 @@ namespace dxvk {
|
|||||||
D3D11CommonTexture::MappedBuffer D3D11CommonTexture::CreateMappedBuffer(UINT MipLevel) const {
|
D3D11CommonTexture::MappedBuffer D3D11CommonTexture::CreateMappedBuffer(UINT MipLevel) const {
|
||||||
const DxvkFormatInfo* formatInfo = lookupFormatInfo(
|
const DxvkFormatInfo* formatInfo = lookupFormatInfo(
|
||||||
m_device->LookupPackedFormat(m_desc.Format, GetFormatMode()).Format);
|
m_device->LookupPackedFormat(m_desc.Format, GetFormatMode()).Format);
|
||||||
|
|
||||||
|
VkImageSubresource subresource = { };
|
||||||
|
subresource.aspectMask = formatInfo->aspectMask;
|
||||||
|
subresource.mipLevel = MipLevel;
|
||||||
|
|
||||||
DxvkBufferCreateInfo info;
|
DxvkBufferCreateInfo info;
|
||||||
info.size = GetSubresourceLayout(formatInfo->aspectMask, MipLevel).Size;
|
info.size = DetermineSubresourceLayout(nullptr, subresource).Size;
|
||||||
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
||||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||||
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||||
|
@ -390,7 +390,13 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
VkImageSubresource GetSubresourceFromIndex(
|
VkImageSubresource GetSubresourceFromIndex(
|
||||||
VkImageAspectFlags Aspect,
|
VkImageAspectFlags Aspect,
|
||||||
UINT Subresource) const;
|
UINT Subresource) const {
|
||||||
|
VkImageSubresource result;
|
||||||
|
result.aspectMask = Aspect;
|
||||||
|
result.mipLevel = Subresource % m_desc.MipLevels;
|
||||||
|
result.arrayLayer = Subresource / m_desc.MipLevels;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Computes subresource layout for the given subresource
|
* \brief Computes subresource layout for the given subresource
|
||||||
@ -480,8 +486,9 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MappedInfo {
|
struct MappedInfo {
|
||||||
D3D11_MAP mapType;
|
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = { };
|
||||||
uint64_t seq;
|
D3D11_MAP mapType = D3D11_MAP(~0u);
|
||||||
|
uint64_t seq = 0u;
|
||||||
};
|
};
|
||||||
|
|
||||||
ID3D11Resource* m_interface;
|
ID3D11Resource* m_interface;
|
||||||
@ -513,8 +520,12 @@ namespace dxvk {
|
|||||||
D3D11_COMMON_TEXTURE_MAP_MODE DetermineMapMode(
|
D3D11_COMMON_TEXTURE_MAP_MODE DetermineMapMode(
|
||||||
const DxvkImageCreateInfo* pImageInfo) const;
|
const DxvkImageCreateInfo* pImageInfo) const;
|
||||||
|
|
||||||
|
D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT DetermineSubresourceLayout(
|
||||||
|
const DxvkImageCreateInfo* pImageInfo,
|
||||||
|
const VkImageSubresource& subresource) const;
|
||||||
|
|
||||||
void ExportImageInfo();
|
void ExportImageInfo();
|
||||||
|
|
||||||
static BOOL IsR32UavCompatibleFormat(
|
static BOOL IsR32UavCompatibleFormat(
|
||||||
DXGI_FORMAT Format);
|
DXGI_FORMAT Format);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user