1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-29 17:52:18 +01:00

[d3d11] Fixed several mip level-related bugs

- When a D3D11 texture was created with a mip level count of zero,
  DXVK would compute the correct number of mip levels, but not write
  them back to the description field.
- Framebuffers would always use the size of the top level, not the
  mip levels that were actually attached to the framebuffer.
- Several image copy operations did not handle mip levels other
  than the top mip level correctly.
This commit is contained in:
Philip Rebohle 2018-01-06 02:09:07 +01:00
parent f7e1efbaaf
commit 4e06f498dd
6 changed files with 90 additions and 67 deletions

View File

@ -397,13 +397,26 @@ namespace dxvk {
const D3D11TextureInfo* dstTextureInfo = GetCommonTextureInfo(pDstResource);
const D3D11TextureInfo* srcTextureInfo = GetCommonTextureInfo(pSrcResource);
const DxvkFormatInfo* dstFormatInfo = imageFormatInfo(dstTextureInfo->image->info().format);
const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcTextureInfo->image->info().format);
const VkImageSubresource dstSubresource =
GetSubresourceFromIndex(
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
dstTextureInfo->image->info().mipLevels, DstSubresource);
const VkImageSubresource srcSubresource =
GetSubresourceFromIndex(
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
srcTextureInfo->image->info().mipLevels, SrcSubresource);
VkOffset3D srcOffset = { 0, 0, 0 };
VkOffset3D dstOffset = {
static_cast<int32_t>(DstX),
static_cast<int32_t>(DstY),
static_cast<int32_t>(DstZ) };
VkExtent3D extent = srcTextureInfo->image->info().extent;
VkExtent3D extent = srcTextureInfo->image->mipLevelExtent(srcSubresource.mipLevel);
if (pSrcBox != nullptr) {
if (pSrcBox->left >= pSrcBox->right
@ -420,19 +433,6 @@ namespace dxvk {
extent.depth = pSrcBox->back - pSrcBox->front;
}
const DxvkFormatInfo* dstFormatInfo = imageFormatInfo(dstTextureInfo->image->info().format);
const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcTextureInfo->image->info().format);
const VkImageSubresource dstSubresource =
GetSubresourceFromIndex(
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
dstTextureInfo->image->info().mipLevels, DstSubresource);
const VkImageSubresource srcSubresource =
GetSubresourceFromIndex(
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
srcTextureInfo->image->info().mipLevels, SrcSubresource);
const VkImageSubresourceLayers dstLayers = {
dstSubresource.aspectMask,
dstSubresource.mipLevel,
@ -529,8 +529,8 @@ namespace dxvk {
VkClearRect clearRect;
clearRect.rect.offset.x = 0;
clearRect.rect.offset.y = 0;
clearRect.rect.extent.width = dxvkView->imageInfo().extent.width;
clearRect.rect.extent.height = dxvkView->imageInfo().extent.height;
clearRect.rect.extent.width = dxvkView->mipLevelExtent(0).width;
clearRect.rect.extent.height = dxvkView->mipLevelExtent(0).height;
clearRect.baseArrayLayer = 0;
clearRect.layerCount = dxvkView->imageInfo().numLayers;
@ -591,8 +591,8 @@ namespace dxvk {
VkClearRect clearRect;
clearRect.rect.offset.x = 0;
clearRect.rect.offset.y = 0;
clearRect.rect.extent.width = dxvkView->imageInfo().extent.width;
clearRect.rect.extent.height = dxvkView->imageInfo().extent.height;
clearRect.rect.extent.width = dxvkView->mipLevelExtent(0).width;
clearRect.rect.extent.height = dxvkView->mipLevelExtent(0).height;
clearRect.baseArrayLayer = 0;
clearRect.layerCount = dxvkView->imageInfo().numLayers;
@ -651,8 +651,12 @@ namespace dxvk {
const D3D11TextureInfo* textureInfo
= GetCommonTextureInfo(pDstResource);
const VkImageSubresource subresource =
GetSubresourceFromIndex(VK_IMAGE_ASPECT_COLOR_BIT,
textureInfo->image->info().mipLevels, DstSubresource);
VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = textureInfo->image->info().extent;
VkExtent3D extent = textureInfo->image->mipLevelExtent(subresource.mipLevel);
if (pDstBox != nullptr) {
if (pDstBox->left >= pDstBox->right
@ -669,15 +673,10 @@ namespace dxvk {
extent.depth = pDstBox->back - pDstBox->front;
}
const VkImageSubresource imageSubresource =
GetSubresourceFromIndex(VK_IMAGE_ASPECT_COLOR_BIT,
textureInfo->image->info().mipLevels, DstSubresource);
VkImageSubresourceLayers layers;
layers.aspectMask = imageSubresource.aspectMask;
layers.mipLevel = imageSubresource.mipLevel;
layers.baseArrayLayer = imageSubresource.arrayLayer;
layers.layerCount = 1;
const VkImageSubresourceLayers layers = {
subresource.aspectMask,
subresource.mipLevel,
subresource.arrayLayer, 1 };
m_context->updateImage(
textureInfo->image, layers,

View File

@ -304,7 +304,7 @@ namespace dxvk {
return E_INVALIDARG;
}
if (viewInfo.numLevels == 0 || viewInfo.numLevels == 0xFFFFFFFF)
if (viewInfo.numLevels == 0xFFFFFFFF)
viewInfo.numLevels = textureInfo->image->info().mipLevels - viewInfo.minLevel;
if (ppSRView == nullptr)
@ -445,7 +445,7 @@ namespace dxvk {
default:
Logger::err(str::format(
"D3D11: View dimension not supported for SRV: ",
"D3D11: View dimension not supported for UAV: ",
desc.ViewDimension));
return E_INVALIDARG;
}

View File

@ -149,9 +149,6 @@ namespace dxvk {
if (MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
pImageInfo->flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
if (pImageInfo->mipLevels == 0)
pImageInfo->mipLevels = util::computeMipLevelCount(pImageInfo->extent);
if (pImageInfo->tiling == VK_IMAGE_TILING_OPTIMAL)
pImageInfo->layout = OptimizeLayout(pImageInfo->usage);
}
@ -164,18 +161,23 @@ namespace dxvk {
m_desc (*pDesc) {
const DxgiFormatMode formatMode
= GetFormatModeFromBindFlags(pDesc->BindFlags);
= GetFormatModeFromBindFlags(m_desc.BindFlags);
if (m_desc.MipLevels == 0) {
m_desc.MipLevels = util::computeMipLevelCount(
{ m_desc.Width, 1u, 1u });
}
DxvkImageCreateInfo info;
info.type = VK_IMAGE_TYPE_1D;
info.format = pDevice->LookupFormat(pDesc->Format, formatMode).format;
info.format = pDevice->LookupFormat(m_desc.Format, formatMode).format;
info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
info.sampleCount = VK_SAMPLE_COUNT_1_BIT;
info.extent.width = pDesc->Width;
info.extent.width = m_desc.Width;
info.extent.height = 1;
info.extent.depth = 1;
info.numLayers = pDesc->ArraySize;
info.mipLevels = pDesc->MipLevels;
info.numLayers = m_desc.ArraySize;
info.mipLevels = m_desc.MipLevels;
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
@ -186,16 +188,16 @@ namespace dxvk {
GetImageStagesAndAccessFlags(
pDevice,
pDesc->BindFlags,
pDesc->CPUAccessFlags,
pDesc->MiscFlags,
m_desc.BindFlags,
m_desc.CPUAccessFlags,
m_desc.MiscFlags,
&info);
// Create the image and, if necessary, the image buffer
m_texInfo.formatMode = formatMode;
m_texInfo.image = pDevice->GetDXVKDevice()->createImage(
info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_texInfo.imageBuffer = pDesc->CPUAccessFlags != 0
m_texInfo.imageBuffer = m_desc.CPUAccessFlags != 0
? CreateImageBuffer(pDevice->GetDXVKDevice(), info.format, info.extent)
: nullptr;
}
@ -253,18 +255,23 @@ namespace dxvk {
m_desc (*pDesc) {
const DxgiFormatMode formatMode
= GetFormatModeFromBindFlags(pDesc->BindFlags);
= GetFormatModeFromBindFlags(m_desc.BindFlags);
if (m_desc.MipLevels == 0) {
m_desc.MipLevels = util::computeMipLevelCount(
{ m_desc.Width, m_desc.Height, 1u });
}
DxvkImageCreateInfo info;
info.type = VK_IMAGE_TYPE_2D;
info.format = pDevice->LookupFormat(pDesc->Format, formatMode).format;
info.format = pDevice->LookupFormat(m_desc.Format, formatMode).format;
info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
info.sampleCount = VK_SAMPLE_COUNT_1_BIT;
info.extent.width = pDesc->Width;
info.extent.height = pDesc->Height;
info.extent.width = m_desc.Width;
info.extent.height = m_desc.Height;
info.extent.depth = 1;
info.numLayers = pDesc->ArraySize;
info.mipLevels = pDesc->MipLevels;
info.numLayers = m_desc.ArraySize;
info.mipLevels = m_desc.MipLevels;
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
@ -273,21 +280,21 @@ namespace dxvk {
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.layout = VK_IMAGE_LAYOUT_GENERAL;
if (FAILED(GetSampleCount(pDesc->SampleDesc.Count, &info.sampleCount)))
throw DxvkError(str::format("D3D11: Invalid sample count: ", pDesc->SampleDesc.Count));
if (FAILED(GetSampleCount(m_desc.SampleDesc.Count, &info.sampleCount)))
throw DxvkError(str::format("D3D11: Invalid sample count: ", m_desc.SampleDesc.Count));
GetImageStagesAndAccessFlags(
pDevice,
pDesc->BindFlags,
pDesc->CPUAccessFlags,
pDesc->MiscFlags,
m_desc.BindFlags,
m_desc.CPUAccessFlags,
m_desc.MiscFlags,
&info);
// Create the image and, if necessary, the image buffer
m_texInfo.formatMode = formatMode;
m_texInfo.image = pDevice->GetDXVKDevice()->createImage(
info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_texInfo.imageBuffer = pDesc->CPUAccessFlags != 0
m_texInfo.imageBuffer = m_desc.CPUAccessFlags != 0
? CreateImageBuffer(pDevice->GetDXVKDevice(), info.format, info.extent)
: nullptr;
}
@ -344,19 +351,24 @@ namespace dxvk {
m_desc (*pDesc) {
const DxgiFormatMode formatMode
= GetFormatModeFromBindFlags(pDesc->BindFlags);
= GetFormatModeFromBindFlags(m_desc.BindFlags);
if (m_desc.MipLevels == 0) {
m_desc.MipLevels = util::computeMipLevelCount(
{ m_desc.Width, m_desc.Height, m_desc.Depth });
}
DxvkImageCreateInfo info;
info.type = VK_IMAGE_TYPE_3D;
info.format = pDevice->LookupFormat(pDesc->Format, formatMode).format;
info.format = pDevice->LookupFormat(m_desc.Format, formatMode).format;
info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
| VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
info.sampleCount = VK_SAMPLE_COUNT_1_BIT;
info.extent.width = pDesc->Width;
info.extent.height = pDesc->Height;
info.extent.depth = pDesc->Depth;
info.extent.width = m_desc.Width;
info.extent.height = m_desc.Height;
info.extent.depth = m_desc.Depth;
info.numLayers = 1;
info.mipLevels = pDesc->MipLevels;
info.mipLevels = m_desc.MipLevels;
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
@ -367,16 +379,16 @@ namespace dxvk {
GetImageStagesAndAccessFlags(
pDevice,
pDesc->BindFlags,
pDesc->CPUAccessFlags,
pDesc->MiscFlags,
m_desc.BindFlags,
m_desc.CPUAccessFlags,
m_desc.MiscFlags,
&info);
// Create the image and, if necessary, the image buffer
m_texInfo.formatMode = formatMode;
m_texInfo.image = pDevice->GetDXVKDevice()->createImage(
info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_texInfo.imageBuffer = pDesc->CPUAccessFlags != 0
m_texInfo.imageBuffer = m_desc.CPUAccessFlags != 0
? CreateImageBuffer(pDevice->GetDXVKDevice(), info.format, info.extent)
: nullptr;
}

View File

@ -304,7 +304,7 @@ namespace dxvk {
m_barriers.accessImage(
dstImage, dstSubresourceRange,
dstImage->info().extent == dstExtent
dstImage->mipLevelExtent(dstSubresource.mipLevel) == dstExtent
? VK_IMAGE_LAYOUT_UNDEFINED
: dstImage->info().layout,
dstImage->info().stages,
@ -367,7 +367,7 @@ namespace dxvk {
m_barriers.accessImage(
dstImage, dstSubresourceRange,
dstImage->info().extent == extent
dstImage->mipLevelExtent(dstSubresource.mipLevel) == extent
? VK_IMAGE_LAYOUT_UNDEFINED
: dstImage->info().layout,
dstImage->info().stages,

View File

@ -65,7 +65,7 @@ namespace dxvk {
DxvkFramebufferSize DxvkRenderTargets::renderTargetSize(
const Rc<DxvkImageView>& renderTarget) const {
auto extent = renderTarget->image()->info().extent;
auto extent = renderTarget->mipLevelExtent(0);
auto layers = renderTarget->info().numLayers;
return DxvkFramebufferSize { extent.width, extent.height, layers };
}

View File

@ -243,6 +243,18 @@ namespace dxvk {
return m_image;
}
/**
* \brief Mip level size
*
* Computes the mip level size relative to
* the first mip level that the view includes.
* \param [in] level Mip level
* \returns Size of that level
*/
VkExtent3D mipLevelExtent(uint32_t level) const {
return m_image->mipLevelExtent(level + m_info.minLevel);
}
/**
* \brief Subresource range
* \returns Subresource range