diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index b1c57453..c896f7dd 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1666,19 +1666,34 @@ namespace dxvk { this->spillRenderPass(false); this->invalidateState(); - // Create image views, etc. - Rc mipGenerator = new DxvkMetaMipGenRenderPass(m_device->vkd(), imageView); - + // Make sure we can both render to and read from the image + VkFormat viewFormat = imageView->info().format; + + DxvkImageUsageInfo usageInfo; + usageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + usageInfo.viewFormatCount = 1; + usageInfo.viewFormats = &viewFormat; + + if (!ensureImageCompatibility(imageView->image(), usageInfo)) { + Logger::err(str::format("DxvkContext: generateMipmaps: Unsupported operation:" + "\n view format: ", imageView->info().format, + "\n image format: ", imageView->image()->info().format)); + return; + } + if (m_execBarriers.isImageDirty(imageView->image(), imageView->imageSubresources(), DxvkAccess::Write)) m_execBarriers.recordCommands(m_cmd); + // Create image views, etc. + DxvkMetaMipGenViews mipGenerator(imageView); + VkImageLayout dstLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VkImageLayout srcLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); // If necessary, transition first mip level to the read-only layout if (imageView->image()->info().layout != srcLayout) { m_execAcquires.accessImage(imageView->image(), - mipGenerator->getTopSubresource(), + mipGenerator.getTopSubresource(), imageView->image()->info().layout, imageView->image()->info().stages, 0, srcLayout, @@ -1689,7 +1704,7 @@ namespace dxvk { // If necessary, initialize all levels that are written to if (imageView->image()->info().layout != dstLayout) { m_execAcquires.accessImage(imageView->image(), - mipGenerator->getAllTargetSubresources(), + mipGenerator.getAllTargetSubresources(), VK_IMAGE_LAYOUT_UNDEFINED, imageView->image()->info().stages, 0, dstLayout, @@ -1724,14 +1739,14 @@ namespace dxvk { // Retrieve a compatible pipeline to use for rendering DxvkMetaBlitPipeline pipeInfo = m_common->metaBlit().getPipeline( - mipGenerator->getSrcViewType(), imageView->info().format, VK_SAMPLE_COUNT_1_BIT); + mipGenerator.getSrcViewType(), imageView->info().format, VK_SAMPLE_COUNT_1_BIT); - for (uint32_t i = 0; i < mipGenerator->getPassCount(); i++) { + for (uint32_t i = 0; i < mipGenerator.getPassCount(); i++) { // Width, height and layer count for the current pass - VkExtent3D passExtent = mipGenerator->computePassExtent(i); + VkExtent3D passExtent = mipGenerator.computePassExtent(i); // Create descriptor set with the current source view - descriptorImage.imageView = mipGenerator->getSrcView(i); + descriptorImage.imageView = mipGenerator.getSrcViewHandle(i); descriptorWrite.dstSet = m_descriptorPool->alloc(pipeInfo.dsetLayout); m_cmd->updateDescriptorSets(1, &descriptorWrite); @@ -1749,7 +1764,7 @@ namespace dxvk { scissor.extent = { passExtent.width, passExtent.height }; // Set up rendering info - attachmentInfo.imageView = mipGenerator->getDstView(i); + attachmentInfo.imageView = mipGenerator.getDstViewHandle(i); renderingInfo.renderArea = scissor; renderingInfo.layerCount = passExtent.depth; @@ -1761,7 +1776,7 @@ namespace dxvk { if (i) { m_execAcquires.accessImage(imageView->image(), - mipGenerator->getSourceSubresource(i), + mipGenerator.getSourceSubresource(i), dstLayout, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, @@ -1804,7 +1819,7 @@ namespace dxvk { imageView->image()->info().access); } else { m_execBarriers.accessImage(imageView->image(), - mipGenerator->getAllSourceSubresources(), + mipGenerator.getAllSourceSubresources(), srcLayout, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, @@ -1815,7 +1830,7 @@ namespace dxvk { imageView->image()->info().access); m_execBarriers.accessImage(imageView->image(), - mipGenerator->getBottomSubresource(), + mipGenerator.getBottomSubresource(), dstLayout, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, @@ -1824,7 +1839,6 @@ namespace dxvk { imageView->image()->info().access); } - m_cmd->trackResource(mipGenerator); m_cmd->trackResource(imageView->image()); } diff --git a/src/dxvk/dxvk_meta_mipgen.cpp b/src/dxvk/dxvk_meta_mipgen.cpp index abe50c8e..a90d7fb7 100644 --- a/src/dxvk/dxvk_meta_mipgen.cpp +++ b/src/dxvk/dxvk_meta_mipgen.cpp @@ -2,10 +2,9 @@ namespace dxvk { - DxvkMetaMipGenRenderPass::DxvkMetaMipGenRenderPass( - const Rc& vkd, + DxvkMetaMipGenViews::DxvkMetaMipGenViews( const Rc& view) - : m_vkd(vkd), m_view(view) { + : m_view(view) { // Determine view type based on image type const std::array, 3> viewTypes = {{ { VK_IMAGE_VIEW_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_1D_ARRAY }, @@ -24,15 +23,12 @@ namespace dxvk { } - DxvkMetaMipGenRenderPass::~DxvkMetaMipGenRenderPass() { - for (const auto& views : m_passes) { - m_vkd->vkDestroyImageView(m_vkd->device(), views.src, nullptr); - m_vkd->vkDestroyImageView(m_vkd->device(), views.dst, nullptr); - } + DxvkMetaMipGenViews::~DxvkMetaMipGenViews() { + } - VkExtent3D DxvkMetaMipGenRenderPass::computePassExtent(uint32_t passId) const { + VkExtent3D DxvkMetaMipGenViews::computePassExtent(uint32_t passId) const { VkExtent3D extent = m_view->mipLevelExtent(passId + 1); if (m_view->image()->info().type != VK_IMAGE_TYPE_3D) @@ -42,54 +38,43 @@ namespace dxvk { } - DxvkMetaMipGenRenderPass::PassViews DxvkMetaMipGenRenderPass::createViews(uint32_t pass) const { + DxvkMetaMipGenViews::PassViews DxvkMetaMipGenViews::createViews(uint32_t pass) const { PassViews result = { }; - VkImageViewUsageCreateInfo usageInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO }; + // Source image view + DxvkImageViewKey srcViewInfo; + srcViewInfo.viewType = m_srcViewType; + srcViewInfo.format = m_view->info().format; + srcViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + srcViewInfo.aspects = m_view->info().aspects; + srcViewInfo.mipIndex = m_view->info().mipIndex + pass; + srcViewInfo.mipCount = 1; + srcViewInfo.layerIndex = m_view->info().layerIndex; + srcViewInfo.layerCount = m_view->info().layerCount; - VkImageViewCreateInfo viewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, &usageInfo }; - viewInfo.image = m_view->image()->handle(); - viewInfo.format = m_view->info().format; - - // Create source image view, which points to - // the one mip level we're going to sample. - VkImageSubresourceRange srcSubresources; - srcSubresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - srcSubresources.baseMipLevel = m_view->info().mipIndex + pass; - srcSubresources.levelCount = 1; - srcSubresources.baseArrayLayer = m_view->info().layerIndex; - srcSubresources.layerCount = m_view->info().layerCount; - - usageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - viewInfo.viewType = m_srcViewType; - viewInfo.subresourceRange = srcSubresources; - - if (m_vkd->vkCreateImageView(m_vkd->device(), &viewInfo, nullptr, &result.src) != VK_SUCCESS) - throw DxvkError("DxvkMetaMipGenRenderPass: Failed to create source image view"); + result.src = m_view->image()->createView(srcViewInfo); // Create destination image view, which points // to the mip level we're going to render to. VkExtent3D dstExtent = m_view->mipLevelExtent(pass + 1); - VkImageSubresourceRange dstSubresources; - dstSubresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - dstSubresources.baseMipLevel = m_view->info().mipIndex + pass + 1; - dstSubresources.levelCount = 1; + DxvkImageViewKey dstViewInfo; + dstViewInfo.viewType = m_dstViewType; + dstViewInfo.format = m_view->info().format; + dstViewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + dstViewInfo.aspects = m_view->info().aspects; + dstViewInfo.mipIndex = m_view->info().mipIndex + pass + 1; + dstViewInfo.mipCount = 1u; if (m_view->image()->info().type != VK_IMAGE_TYPE_3D) { - dstSubresources.baseArrayLayer = m_view->info().layerIndex; - dstSubresources.layerCount = m_view->info().layerCount; + dstViewInfo.layerIndex = m_view->info().layerIndex; + dstViewInfo.layerCount = m_view->info().layerCount; } else { - dstSubresources.baseArrayLayer = 0; - dstSubresources.layerCount = dstExtent.depth; + dstViewInfo.layerIndex = 0; + dstViewInfo.layerCount = dstExtent.depth; } - - usageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - viewInfo.viewType = m_dstViewType; - viewInfo.subresourceRange = dstSubresources; - - if (m_vkd->vkCreateImageView(m_vkd->device(), &viewInfo, nullptr, &result.dst) != VK_SUCCESS) - throw DxvkError("DxvkMetaMipGenRenderPass: Failed to create destination image view"); + + result.dst = m_view->image()->createView(dstViewInfo); return result; } diff --git a/src/dxvk/dxvk_meta_mipgen.h b/src/dxvk/dxvk_meta_mipgen.h index e473816d..ddbb16fb 100644 --- a/src/dxvk/dxvk_meta_mipgen.h +++ b/src/dxvk/dxvk_meta_mipgen.h @@ -2,6 +2,8 @@ #include +#include "../util/util_small_vector.h" + #include "dxvk_meta_blit.h" namespace dxvk { @@ -13,15 +15,14 @@ namespace dxvk { * a render pass object for mip map generation. * This must be created per image view. */ - class DxvkMetaMipGenRenderPass : public DxvkResource { + class DxvkMetaMipGenViews { public: - DxvkMetaMipGenRenderPass( - const Rc& vkd, + DxvkMetaMipGenViews( const Rc& view); - ~DxvkMetaMipGenRenderPass(); + ~DxvkMetaMipGenViews(); /** * \brief Source image view type @@ -50,8 +51,8 @@ namespace dxvk { * \param [in] pass Render pass index * \returns Source image view handle for the given pass */ - VkImageView getSrcView(uint32_t passId) const { - return m_passes.at(passId).src; + VkImageView getSrcViewHandle(uint32_t passId) const { + return m_passes[passId].src->handle(); } /** @@ -60,8 +61,8 @@ namespace dxvk { * \param [in] pass Render pass index * \returns Destination image view handle for the given pass */ - VkImageView getDstView(uint32_t passId) const { - return m_passes.at(passId).dst; + VkImageView getDstViewHandle(uint32_t passId) const { + return m_passes[passId].dst->handle(); } /** @@ -130,17 +131,16 @@ namespace dxvk { private: struct PassViews { - VkImageView src; - VkImageView dst; + Rc src; + Rc dst; }; - Rc m_vkd; Rc m_view; - VkImageViewType m_srcViewType; - VkImageViewType m_dstViewType; + VkImageViewType m_srcViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + VkImageViewType m_dstViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; - std::vector m_passes; + small_vector m_passes; PassViews createViews(uint32_t pass) const;