From 4b37590e1419deb3e3ef242e5fbb8d3cfacb3b61 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 25 May 2018 17:45:41 +0200 Subject: [PATCH] [dxvk] Use new mip map generator --- src/d3d11/d3d11_context.cpp | 4 +- src/dxvk/dxvk_context.cpp | 209 +++++++++++++++++------------------- src/dxvk/dxvk_context.h | 17 +-- src/dxvk/dxvk_device.cpp | 26 ++--- src/dxvk/dxvk_device.h | 1 + 5 files changed, 126 insertions(+), 131 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 9e922901..bf330af5 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -856,9 +856,7 @@ namespace dxvk { if (view->GetResourceType() != D3D11_RESOURCE_DIMENSION_BUFFER) { EmitCs([cDstImageView = view->GetImageView()] (DxvkContext* ctx) { - ctx->generateMipmaps( - cDstImageView->image(), - cDstImageView->subresources()); + ctx->generateMipmaps(cDstImageView); }); } else { Logger::err("D3D11: GenerateMips called on a buffer"); diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index afad9756..f440ef64 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -7,12 +7,14 @@ namespace dxvk { DxvkContext::DxvkContext( - const Rc& device, - const Rc& pipelineManager, - const Rc& metaClearObjects) + const Rc& device, + const Rc& pipelineManager, + const Rc& metaClearObjects, + const Rc& metaMipGenObjects) : m_device (device), m_pipeMgr (pipelineManager), - m_metaClear (metaClearObjects) { } + m_metaClear (metaClearObjects), + m_metaMipGen(metaMipGenObjects) { } DxvkContext::~DxvkContext() { @@ -976,123 +978,102 @@ namespace dxvk { void DxvkContext::generateMipmaps( - const Rc& image, - const VkImageSubresourceRange& subresources) { - if (subresources.levelCount <= 1) + const Rc& imageView) { + if (imageView->info().numLevels <= 1) return; this->spillRenderPass(); - - // The top-most level will only be read. We can - // discard the contents of all the lower levels - // since we're going to override them anyway. - m_barriers.accessImage(image, - VkImageSubresourceRange { - subresources.aspectMask, - subresources.baseMipLevel, 1, - subresources.baseArrayLayer, - subresources.layerCount }, - image->info().layout, - image->info().stages, - image->info().access, - image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT); + this->unbindGraphicsPipeline(); - m_barriers.accessImage(image, - VkImageSubresourceRange { - subresources.aspectMask, - subresources.baseMipLevel + 1, - subresources.levelCount - 1, - subresources.baseArrayLayer, - subresources.layerCount }, - VK_IMAGE_LAYOUT_UNDEFINED, - image->info().stages, - image->info().access, - image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT); + // Create the a set of framebuffers and image views + const Rc mipGenerator + = new DxvkMetaMipGenRenderPass(m_device->vkd(), imageView); - m_barriers.recordCommands(m_cmd); + // Common descriptor set properties that we use to + // bind the source image view to the fragment shader + VkDescriptorImageInfo descriptorImage; + descriptorImage.sampler = VK_NULL_HANDLE; + descriptorImage.imageView = VK_NULL_HANDLE; + descriptorImage.imageLayout = imageView->imageInfo().layout; - // Generate each individual mip level with a blit - for (uint32_t i = 1; i < subresources.levelCount; i++) { - const uint32_t mip = subresources.baseMipLevel + i; + VkWriteDescriptorSet descriptorWrite; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.pNext = nullptr; + descriptorWrite.dstSet = VK_NULL_HANDLE; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorCount = 1; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrite.pImageInfo = &descriptorImage; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pTexelBufferView = nullptr; + + // Common render pass info + VkRenderPassBeginInfo passInfo; + passInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + passInfo.pNext = nullptr; + passInfo.renderPass = mipGenerator->renderPass(); + passInfo.framebuffer = VK_NULL_HANDLE; + passInfo.renderArea = VkRect2D { }; + passInfo.clearValueCount = 0; + passInfo.pClearValues = nullptr; + + // Retrieve a compatible pipeline to use for rendering + DxvkMetaMipGenPipeline pipeInfo = m_metaMipGen->getPipeline( + mipGenerator->viewType(), imageView->info().format); + + for (uint32_t i = 0; i < mipGenerator->passCount(); i++) { + DxvkMetaMipGenPass pass = mipGenerator->pass(i); - const VkExtent3D srcExtent = image->mipLevelExtent(mip - 1); - const VkExtent3D dstExtent = image->mipLevelExtent(mip); + // Width, height and layer count for the current pass + VkExtent3D passExtent = mipGenerator->passExtent(i); - VkImageBlit region; - region.srcSubresource = VkImageSubresourceLayers { - subresources.aspectMask, mip - 1, - subresources.baseArrayLayer, - subresources.layerCount }; - region.srcOffsets[0] = VkOffset3D { 0, 0, 0 }; - region.srcOffsets[1].x = srcExtent.width; - region.srcOffsets[1].y = srcExtent.height; - region.srcOffsets[1].z = srcExtent.depth; + // Create descriptor set with the current source view + descriptorImage.imageView = pass.srcView; + descriptorWrite.dstSet = m_cmd->allocateDescriptorSet(pipeInfo.dsetLayout); + m_cmd->updateDescriptorSets(1, &descriptorWrite); - region.dstSubresource = VkImageSubresourceLayers { - subresources.aspectMask, mip, - subresources.baseArrayLayer, - subresources.layerCount }; - region.dstOffsets[0] = VkOffset3D { 0, 0, 0 }; - region.dstOffsets[1].x = dstExtent.width; - region.dstOffsets[1].y = dstExtent.height; - region.dstOffsets[1].z = dstExtent.depth; + // Set up viewport and scissor rect + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = float(passExtent.width); + viewport.height = float(passExtent.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; - m_cmd->cmdBlitImage( - image->handle(), image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), - image->handle(), image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), - 1, ®ion, VK_FILTER_LINEAR); + VkRect2D scissor; + scissor.offset = { 0, 0 }; + scissor.extent = { passExtent.width, passExtent.height }; - if (i + 1 < subresources.levelCount) { - m_barriers.accessImage(image, - VkImageSubresourceRange { - subresources.aspectMask, mip, 1, - subresources.baseArrayLayer, - subresources.layerCount }, - image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, - image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT); - m_barriers.recordCommands(m_cmd); - } + // Set up render pass info + passInfo.framebuffer = pass.framebuffer; + passInfo.renderArea = scissor; + + // Set up push constants + DxvkMetaMipGenPushConstants pushConstants; + pushConstants.layerCount = passExtent.depth; + + m_cmd->cmdBeginRenderPass(&passInfo, VK_SUBPASS_CONTENTS_INLINE); + m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle); + m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeInfo.pipeLayout, descriptorWrite.dstSet); + + m_cmd->cmdSetViewport(0, 1, &viewport); + m_cmd->cmdSetScissor (0, 1, &scissor); + + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof(pushConstants), + &pushConstants); + + m_cmd->cmdDraw(1, passExtent.depth, 0, 0); + m_cmd->cmdEndRenderPass(); } - // Transform mip levels back into their original layout. - // The last mip level is still in TRANSFER_DST_OPTIMAL. - m_barriers.accessImage(image, - VkImageSubresourceRange { - subresources.aspectMask, - subresources.baseMipLevel, - subresources.levelCount - 1, - subresources.baseArrayLayer, - subresources.layerCount }, - image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - image->info().layout, - image->info().stages, - image->info().access); - - m_barriers.accessImage(image, - VkImageSubresourceRange { - subresources.aspectMask, - subresources.baseMipLevel - + subresources.levelCount - 1, 1, - subresources.baseArrayLayer, - subresources.layerCount }, - image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, - image->info().layout, - image->info().stages, - image->info().access); - - m_barriers.recordCommands(m_cmd); + m_cmd->trackResource(mipGenerator); + m_cmd->trackResource(imageView); } @@ -1680,6 +1661,18 @@ namespace dxvk { } + void DxvkContext::unbindGraphicsPipeline() { + m_flags.set( + DxvkContextFlag::GpDirtyPipeline, + DxvkContextFlag::GpDirtyPipelineState, + DxvkContextFlag::GpDirtyResources, + DxvkContextFlag::GpDirtyVertexBuffers, + DxvkContextFlag::GpDirtyIndexBuffer); + + m_gpActivePipeline = VK_NULL_HANDLE; + } + + void DxvkContext::updateGraphicsPipeline() { if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) { m_flags.clr(DxvkContextFlag::GpDirtyPipeline); diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index fc74bfe2..24f3ae81 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -7,6 +7,7 @@ #include "dxvk_data.h" #include "dxvk_event.h" #include "dxvk_meta_clear.h" +#include "dxvk_meta_mipgen.h" #include "dxvk_meta_resolve.h" #include "dxvk_pipecache.h" #include "dxvk_pipemanager.h" @@ -28,9 +29,10 @@ namespace dxvk { public: DxvkContext( - const Rc& device, - const Rc& pipelineManager, - const Rc& metaClearObjects); + const Rc& device, + const Rc& pipelineManager, + const Rc& metaClearObjects, + const Rc& metaMipGenObjects); ~DxvkContext(); /** @@ -403,12 +405,10 @@ namespace dxvk { * * Uses blitting to generate lower mip levels from * the top-most mip level passed to this method. - * \param [in] image The image to generate mips for - * \param [in] subresource The subresource range + * \param [in] imageView The image to generate mips for */ void generateMipmaps( - const Rc& image, - const VkImageSubresourceRange& subresources); + const Rc& imageView); /** * \brief Initializes or invalidates an image @@ -621,6 +621,7 @@ namespace dxvk { const Rc m_device; const Rc m_pipeMgr; const Rc m_metaClear; + const Rc m_metaMipGen; Rc m_cmd; DxvkContextFlags m_flags; @@ -654,10 +655,10 @@ namespace dxvk { DxvkRenderPassOps& renderPassOps); void unbindComputePipeline(); - void updateComputePipeline(); void updateComputePipelineState(); + void unbindGraphicsPipeline(); void updateGraphicsPipeline(); void updateGraphicsPipelineState(); diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index a38cb16b..bbee9403 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -8,17 +8,18 @@ namespace dxvk { const Rc& vkd, const Rc& extensions, const VkPhysicalDeviceFeatures& features) - : m_adapter (adapter), - m_vkd (vkd), - m_extensions (extensions), - m_features (features), - m_properties (adapter->deviceProperties()), - m_memory (new DxvkMemoryAllocator (adapter, vkd)), - m_renderPassPool (new DxvkRenderPassPool (vkd)), - m_pipelineManager (new DxvkPipelineManager (this)), - m_metaClearObjects(new DxvkMetaClearObjects (vkd)), - m_unboundResources(this), - m_submissionQueue (this) { + : m_adapter (adapter), + m_vkd (vkd), + m_extensions (extensions), + m_features (features), + m_properties (adapter->deviceProperties()), + m_memory (new DxvkMemoryAllocator (adapter, vkd)), + m_renderPassPool (new DxvkRenderPassPool (vkd)), + m_pipelineManager (new DxvkPipelineManager (this)), + m_metaClearObjects (new DxvkMetaClearObjects (vkd)), + m_metaMipGenObjects (new DxvkMetaMipGenObjects(vkd)), + m_unboundResources (this), + m_submissionQueue (this) { m_graphicsQueue.queueFamily = m_adapter->graphicsQueueFamily(); m_presentQueue.queueFamily = m_adapter->presentQueueFamily(); @@ -106,7 +107,8 @@ namespace dxvk { Rc DxvkDevice::createContext() { return new DxvkContext(this, m_pipelineManager, - m_metaClearObjects); + m_metaClearObjects, + m_metaMipGenObjects); } diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index 9ce2f42f..d7c60652 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -356,6 +356,7 @@ namespace dxvk { Rc m_renderPassPool; Rc m_pipelineManager; Rc m_metaClearObjects; + Rc m_metaMipGenObjects; DxvkUnboundResources m_unboundResources;