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->invalidateState();
// Create image views, etc.
Rc<DxvkMetaMipGenRenderPass> 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<DxvkAccess::None>(mipGenerator);
m_cmd->trackResource<DxvkAccess::Write>(imageView->image());
}

View File

@ -2,10 +2,9 @@
namespace dxvk {
DxvkMetaMipGenRenderPass::DxvkMetaMipGenRenderPass(
const Rc<vk::DeviceFn>& vkd,
DxvkMetaMipGenViews::DxvkMetaMipGenViews(
const Rc<DxvkImageView>& view)
: m_vkd(vkd), m_view(view) {
: m_view(view) {
// Determine view type based on image type
const std::array<std::pair<VkImageViewType, VkImageViewType>, 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;
}

View File

@ -2,6 +2,8 @@
#include <vector>
#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<vk::DeviceFn>& vkd,
DxvkMetaMipGenViews(
const Rc<DxvkImageView>& 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<DxvkImageView> src;
Rc<DxvkImageView> dst;
};
Rc<vk::DeviceFn> m_vkd;
Rc<DxvkImageView> 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<PassViews> m_passes;
small_vector<PassViews, 16> m_passes;
PassViews createViews(uint32_t pass) const;