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:
parent
8c67af680c
commit
58dab7e8c6
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user