From b4f85a2c2f8f9293485c79590abc6828170f87c9 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 10 Dec 2017 19:10:17 +0100 Subject: [PATCH] [d3d11] Fixed mip-mapped texture creation --- src/d3d11/d3d11_device.cpp | 52 +++++++++++++++++++++++++------------- src/dxvk/dxvk_context.cpp | 2 +- src/dxvk/dxvk_image.h | 8 ++++++ src/dxvk/dxvk_util.cpp | 14 ++++++++++ src/dxvk/dxvk_util.h | 7 +++++ 5 files changed, 65 insertions(+), 18 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 855b9f254..e0623aac2 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -229,6 +229,9 @@ namespace dxvk { if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + if (pDesc->MipLevels == 0) + info.mipLevels = util::computeMipLevelCount(info.extent); + if (ppTexture2D != nullptr) { Com image; @@ -1178,29 +1181,44 @@ namespace dxvk { m_dxvkDevice->createCommandList()); const Rc image = pImage->GetDXVKImage(); - - VkImageSubresourceRange subresources; - subresources.aspectMask = imageFormatInfo(image->info().format)->aspectMask; - subresources.baseMipLevel = 0; - subresources.levelCount = image->info().mipLevels; - subresources.baseArrayLayer = 0; - subresources.layerCount = image->info().numLayers; - m_resourceInitContext->initImage(image, subresources); + const DxvkFormatInfo* formatInfo = imageFormatInfo(image->info().format); if (pInitialData != nullptr) { + // pInitialData is an array that stores an entry for + // every single subresource. Since we will define all + // subresources, this counts as initialization. VkImageSubresourceLayers subresourceLayers; - subresourceLayers.aspectMask = subresources.aspectMask; + subresourceLayers.aspectMask = formatInfo->aspectMask; subresourceLayers.mipLevel = 0; subresourceLayers.baseArrayLayer = 0; - subresourceLayers.layerCount = subresources.layerCount; + subresourceLayers.layerCount = 1; - m_resourceInitContext->updateImage( - image, subresourceLayers, - VkOffset3D { 0, 0, 0 }, - image->info().extent, - pInitialData->pSysMem, - pInitialData->SysMemPitch, - pInitialData->SysMemSlicePitch); + for (uint32_t layer = 0; layer < image->info().numLayers; layer++) { + for (uint32_t level = 0; level < image->info().mipLevels; level++) { + subresourceLayers.baseArrayLayer = layer; + subresourceLayers.mipLevel = level; + + const uint32_t id = D3D11CalcSubresource( + level, layer, image->info().mipLevels); + + m_resourceInitContext->updateImage( + image, subresourceLayers, + VkOffset3D { 0, 0, 0 }, + image->mipLevelExtent(level), + pInitialData[id].pSysMem, + pInitialData[id].SysMemPitch, + pInitialData[id].SysMemSlicePitch); + } + } + } else { + // Leave the image contents undefined + VkImageSubresourceRange subresources; + subresources.aspectMask = formatInfo->aspectMask; + subresources.baseMipLevel = 0; + subresources.levelCount = image->info().mipLevels; + subresources.baseArrayLayer = 0; + subresources.layerCount = image->info().numLayers; + m_resourceInitContext->initImage(image, subresources); } m_dxvkDevice->submitCommandList( diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 85c9e5090..b61ddec5e 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -480,7 +480,7 @@ namespace dxvk { m_barriers.accessImage( image, subresourceRange, - image->info().extent == imageExtent + image->mipLevelExtent(subresources.mipLevel) == imageExtent ? VK_IMAGE_LAYOUT_UNDEFINED : image->info().layout, image->info().stages, diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h index b21347baf..0dd8b83e8 100644 --- a/src/dxvk/dxvk_image.h +++ b/src/dxvk/dxvk_image.h @@ -132,6 +132,14 @@ namespace dxvk { return m_info; } + VkExtent3D mipLevelExtent(uint32_t level) const { + VkExtent3D size = m_info.extent; + size.width = std::max(1u, size.width >> level); + size.height = std::max(1u, size.height >> level); + size.depth = std::max(1u, size.depth >> level); + return size; + } + private: Rc m_vkd; diff --git a/src/dxvk/dxvk_util.cpp b/src/dxvk/dxvk_util.cpp index 2b4cb3b86..23356d2d8 100644 --- a/src/dxvk/dxvk_util.cpp +++ b/src/dxvk/dxvk_util.cpp @@ -20,6 +20,20 @@ namespace dxvk::util { return result; } + + uint32_t computeMipLevelCount(VkExtent3D imageSize) { + uint32_t maxDim = std::max(imageSize.width, imageSize.height); + maxDim = std::max(imageSize.depth, maxDim); + uint32_t mipCnt = 0; + + while (maxDim > 0) { + mipCnt += 1; + maxDim /= 2; + } + + return mipCnt; + } + } bool operator == (VkExtent3D a, VkExtent3D b) { diff --git a/src/dxvk/dxvk_util.h b/src/dxvk/dxvk_util.h index c52f32404..f101ac771 100644 --- a/src/dxvk/dxvk_util.h +++ b/src/dxvk/dxvk_util.h @@ -13,6 +13,13 @@ namespace dxvk::util { VkPipelineStageFlags pipelineStages( VkShaderStageFlags shaderStages); + /** + * \brief Computes number of mip levels for an image + * + * \param [in] imageSize Size of the image + * \returns Number of mipmap layers + */ + uint32_t computeMipLevelCount(VkExtent3D imageSize); }