1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 10:24:12 +01:00

[dxvk] Refactor mip generation

This commit is contained in:
Philip Rebohle 2024-09-28 13:00:35 +02:00 committed by Philip Rebohle
parent 8c67af680c
commit 58dab7e8c6
3 changed files with 72 additions and 73 deletions

View File

@ -1666,19 +1666,34 @@ namespace dxvk {
this->spillRenderPass(false); this->spillRenderPass(false);
this->invalidateState(); this->invalidateState();
// Create image views, etc. // Make sure we can both render to and read from the image
Rc<DxvkMetaMipGenRenderPass> mipGenerator = new DxvkMetaMipGenRenderPass(m_device->vkd(), imageView); 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)) if (m_execBarriers.isImageDirty(imageView->image(), imageView->imageSubresources(), DxvkAccess::Write))
m_execBarriers.recordCommands(m_cmd); m_execBarriers.recordCommands(m_cmd);
// Create image views, etc.
DxvkMetaMipGenViews mipGenerator(imageView);
VkImageLayout dstLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VkImageLayout dstLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkImageLayout srcLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VkImageLayout srcLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// If necessary, transition first mip level to the read-only layout // If necessary, transition first mip level to the read-only layout
if (imageView->image()->info().layout != srcLayout) { if (imageView->image()->info().layout != srcLayout) {
m_execAcquires.accessImage(imageView->image(), m_execAcquires.accessImage(imageView->image(),
mipGenerator->getTopSubresource(), mipGenerator.getTopSubresource(),
imageView->image()->info().layout, imageView->image()->info().layout,
imageView->image()->info().stages, 0, imageView->image()->info().stages, 0,
srcLayout, srcLayout,
@ -1689,7 +1704,7 @@ namespace dxvk {
// If necessary, initialize all levels that are written to // If necessary, initialize all levels that are written to
if (imageView->image()->info().layout != dstLayout) { if (imageView->image()->info().layout != dstLayout) {
m_execAcquires.accessImage(imageView->image(), m_execAcquires.accessImage(imageView->image(),
mipGenerator->getAllTargetSubresources(), mipGenerator.getAllTargetSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
imageView->image()->info().stages, 0, imageView->image()->info().stages, 0,
dstLayout, dstLayout,
@ -1724,14 +1739,14 @@ namespace dxvk {
// Retrieve a compatible pipeline to use for rendering // Retrieve a compatible pipeline to use for rendering
DxvkMetaBlitPipeline pipeInfo = m_common->metaBlit().getPipeline( 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 // 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 // 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); descriptorWrite.dstSet = m_descriptorPool->alloc(pipeInfo.dsetLayout);
m_cmd->updateDescriptorSets(1, &descriptorWrite); m_cmd->updateDescriptorSets(1, &descriptorWrite);
@ -1749,7 +1764,7 @@ namespace dxvk {
scissor.extent = { passExtent.width, passExtent.height }; scissor.extent = { passExtent.width, passExtent.height };
// Set up rendering info // Set up rendering info
attachmentInfo.imageView = mipGenerator->getDstView(i); attachmentInfo.imageView = mipGenerator.getDstViewHandle(i);
renderingInfo.renderArea = scissor; renderingInfo.renderArea = scissor;
renderingInfo.layerCount = passExtent.depth; renderingInfo.layerCount = passExtent.depth;
@ -1761,7 +1776,7 @@ namespace dxvk {
if (i) { if (i) {
m_execAcquires.accessImage(imageView->image(), m_execAcquires.accessImage(imageView->image(),
mipGenerator->getSourceSubresource(i), mipGenerator.getSourceSubresource(i),
dstLayout, dstLayout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
@ -1804,7 +1819,7 @@ namespace dxvk {
imageView->image()->info().access); imageView->image()->info().access);
} else { } else {
m_execBarriers.accessImage(imageView->image(), m_execBarriers.accessImage(imageView->image(),
mipGenerator->getAllSourceSubresources(), mipGenerator.getAllSourceSubresources(),
srcLayout, srcLayout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
@ -1815,7 +1830,7 @@ namespace dxvk {
imageView->image()->info().access); imageView->image()->info().access);
m_execBarriers.accessImage(imageView->image(), m_execBarriers.accessImage(imageView->image(),
mipGenerator->getBottomSubresource(), mipGenerator.getBottomSubresource(),
dstLayout, dstLayout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
@ -1824,7 +1839,6 @@ namespace dxvk {
imageView->image()->info().access); imageView->image()->info().access);
} }
m_cmd->trackResource<DxvkAccess::None>(mipGenerator);
m_cmd->trackResource<DxvkAccess::Write>(imageView->image()); m_cmd->trackResource<DxvkAccess::Write>(imageView->image());
} }

View File

@ -2,10 +2,9 @@
namespace dxvk { namespace dxvk {
DxvkMetaMipGenRenderPass::DxvkMetaMipGenRenderPass( DxvkMetaMipGenViews::DxvkMetaMipGenViews(
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkImageView>& view) const Rc<DxvkImageView>& view)
: m_vkd(vkd), m_view(view) { : m_view(view) {
// Determine view type based on image type // Determine view type based on image type
const std::array<std::pair<VkImageViewType, VkImageViewType>, 3> viewTypes = {{ const std::array<std::pair<VkImageViewType, VkImageViewType>, 3> viewTypes = {{
{ VK_IMAGE_VIEW_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_1D_ARRAY }, { VK_IMAGE_VIEW_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_1D_ARRAY },
@ -24,15 +23,12 @@ namespace dxvk {
} }
DxvkMetaMipGenRenderPass::~DxvkMetaMipGenRenderPass() { DxvkMetaMipGenViews::~DxvkMetaMipGenViews() {
for (const auto& views : m_passes) {
m_vkd->vkDestroyImageView(m_vkd->device(), views.src, nullptr);
m_vkd->vkDestroyImageView(m_vkd->device(), views.dst, nullptr);
}
} }
VkExtent3D DxvkMetaMipGenRenderPass::computePassExtent(uint32_t passId) const { VkExtent3D DxvkMetaMipGenViews::computePassExtent(uint32_t passId) const {
VkExtent3D extent = m_view->mipLevelExtent(passId + 1); VkExtent3D extent = m_view->mipLevelExtent(passId + 1);
if (m_view->image()->info().type != VK_IMAGE_TYPE_3D) 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 = { }; 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 }; result.src = m_view->image()->createView(srcViewInfo);
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");
// Create destination image view, which points // Create destination image view, which points
// to the mip level we're going to render to. // to the mip level we're going to render to.
VkExtent3D dstExtent = m_view->mipLevelExtent(pass + 1); VkExtent3D dstExtent = m_view->mipLevelExtent(pass + 1);
VkImageSubresourceRange dstSubresources; DxvkImageViewKey dstViewInfo;
dstSubresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; dstViewInfo.viewType = m_dstViewType;
dstSubresources.baseMipLevel = m_view->info().mipIndex + pass + 1; dstViewInfo.format = m_view->info().format;
dstSubresources.levelCount = 1; 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) { if (m_view->image()->info().type != VK_IMAGE_TYPE_3D) {
dstSubresources.baseArrayLayer = m_view->info().layerIndex; dstViewInfo.layerIndex = m_view->info().layerIndex;
dstSubresources.layerCount = m_view->info().layerCount; dstViewInfo.layerCount = m_view->info().layerCount;
} else { } else {
dstSubresources.baseArrayLayer = 0; dstViewInfo.layerIndex = 0;
dstSubresources.layerCount = dstExtent.depth; dstViewInfo.layerCount = dstExtent.depth;
} }
usageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; result.dst = m_view->image()->createView(dstViewInfo);
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");
return result; return result;
} }

View File

@ -2,6 +2,8 @@
#include <vector> #include <vector>
#include "../util/util_small_vector.h"
#include "dxvk_meta_blit.h" #include "dxvk_meta_blit.h"
namespace dxvk { namespace dxvk {
@ -13,15 +15,14 @@ namespace dxvk {
* a render pass object for mip map generation. * a render pass object for mip map generation.
* This must be created per image view. * This must be created per image view.
*/ */
class DxvkMetaMipGenRenderPass : public DxvkResource { class DxvkMetaMipGenViews {
public: public:
DxvkMetaMipGenRenderPass( DxvkMetaMipGenViews(
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkImageView>& view); const Rc<DxvkImageView>& view);
~DxvkMetaMipGenRenderPass(); ~DxvkMetaMipGenViews();
/** /**
* \brief Source image view type * \brief Source image view type
@ -50,8 +51,8 @@ namespace dxvk {
* \param [in] pass Render pass index * \param [in] pass Render pass index
* \returns Source image view handle for the given pass * \returns Source image view handle for the given pass
*/ */
VkImageView getSrcView(uint32_t passId) const { VkImageView getSrcViewHandle(uint32_t passId) const {
return m_passes.at(passId).src; return m_passes[passId].src->handle();
} }
/** /**
@ -60,8 +61,8 @@ namespace dxvk {
* \param [in] pass Render pass index * \param [in] pass Render pass index
* \returns Destination image view handle for the given pass * \returns Destination image view handle for the given pass
*/ */
VkImageView getDstView(uint32_t passId) const { VkImageView getDstViewHandle(uint32_t passId) const {
return m_passes.at(passId).dst; return m_passes[passId].dst->handle();
} }
/** /**
@ -130,17 +131,16 @@ namespace dxvk {
private: private:
struct PassViews { struct PassViews {
VkImageView src; Rc<DxvkImageView> src;
VkImageView dst; Rc<DxvkImageView> dst;
}; };
Rc<vk::DeviceFn> m_vkd;
Rc<DxvkImageView> m_view; Rc<DxvkImageView> m_view;
VkImageViewType m_srcViewType; VkImageViewType m_srcViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
VkImageViewType m_dstViewType; VkImageViewType m_dstViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
std::vector<PassViews> m_passes; small_vector<PassViews, 16> m_passes;
PassViews createViews(uint32_t pass) const; PassViews createViews(uint32_t pass) const;