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:
parent
f7e1efbaaf
commit
4e06f498dd
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user