Remove some dependencies to framebuffer and renderpass

This commit is contained in:
CamilleLaVey
2026-09-30 02:47:44 -04:00
parent 41d8da1612
commit efba499fd3
23 changed files with 138 additions and 538 deletions
+14 -34
View File
@@ -31,7 +31,6 @@ FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_c
, m_extent{extent}
{
CreateImages(device);
CreateRenderPasses(device);
CreateSampler(device);
CreateShaders(device);
CreateDescriptorPool(device);
@@ -51,14 +50,6 @@ void FSR::CreateImages(const Device& device) {
}
}
void FSR::CreateRenderPasses(const Device& device) {
m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
for (auto& images : m_dynamic_images) {
images.framebuffers[Easu] = CreateWrappedFramebuffer(device, m_renderpass, images.image_views[Easu], m_extent);
images.framebuffers[Rcas] = CreateWrappedFramebuffer(device, m_renderpass, images.image_views[Rcas], m_extent);
}
}
void FSR::CreateSampler(const Device& device) {
m_sampler = CreateBilinearSampler(device);
}
@@ -112,9 +103,11 @@ void FSR::CreatePipelineLayouts(const Device& device) {
}
void FSR::CreatePipelines(const Device& device) {
m_easu_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout,
m_easu_pipeline = CreateWrappedPipeline(device, VK_FORMAT_R16G16B16A16_SFLOAT,
m_pipeline_layout,
std::tie(m_vert_shader, m_easu_shader));
m_rcas_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout,
m_rcas_pipeline = CreateWrappedPipeline(device, VK_FORMAT_R16G16B16A16_SFLOAT,
m_pipeline_layout,
std::tie(m_vert_shader, m_rcas_shader));
}
@@ -129,19 +122,6 @@ void FSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, siz
device.GetLogical().UpdateDescriptorSets(updates, {});
}
void FSR::UploadImages(const Device& device, Scheduler& scheduler) {
if (!m_images_ready) {
m_images_ready = true;
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
for (auto& image : m_dynamic_images) {
ClearColorImage(cmdbuf, *image.images[Easu]);
ClearColorImage(cmdbuf, *image.images[Rcas]);
}
});
scheduler.Finish();
}
}
VkImageView FSR::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image,
VkImageView source_image_view, VkExtent2D input_image_extent,
const Common::Rectangle<f32>& crop_rect) {
@@ -151,12 +131,11 @@ VkImageView FSR::Draw(const Device& device, Scheduler& scheduler, size_t image_i
VkImage rcas_image = *images.images[Rcas];
VkDescriptorSet easu_descriptor_set = images.descriptor_sets[Easu];
VkDescriptorSet rcas_descriptor_set = images.descriptor_sets[Rcas];
VkFramebuffer easu_framebuffer = *images.framebuffers[Easu];
VkFramebuffer rcas_framebuffer = *images.framebuffers[Rcas];
VkImageView easu_view = *images.image_views[Easu];
VkImageView rcas_view = *images.image_views[Rcas];
VkPipeline easu_pipeline = *m_easu_pipeline;
VkPipeline rcas_pipeline = *m_rcas_pipeline;
VkPipelineLayout pipeline_layout = *m_pipeline_layout;
VkRenderPass renderpass = *m_renderpass;
VkExtent2D extent = m_extent;
const f32 input_image_width = static_cast<f32>(input_image_extent.width);
@@ -179,30 +158,31 @@ VkImageView FSR::Draw(const Device& device, Scheduler& scheduler, size_t image_i
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
FsrRcasCon(rcas_con.data(), sharpening);
UploadImages(device, scheduler);
UpdateDescriptorSets(device, source_image_view, image_index);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([=](vk::CommandBuffer cmdbuf) {
TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, easu_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, renderpass, easu_framebuffer, extent);
TransitionImageLayout(cmdbuf, easu_image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_UNDEFINED);
BeginRendering(cmdbuf, easu_view, extent, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, easu_pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0,
easu_descriptor_set, {});
cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, easu_con);
cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, easu_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, rcas_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, renderpass, rcas_framebuffer, extent);
TransitionImageLayout(cmdbuf, rcas_image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_UNDEFINED);
BeginRendering(cmdbuf, rcas_view, extent, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, rcas_pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0,
rcas_descriptor_set, {});
cmdbuf.PushConstants(pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, rcas_con);
cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, rcas_image, VK_IMAGE_LAYOUT_GENERAL);
});
@@ -24,7 +24,6 @@ public:
private:
void CreateImages(const Device& device);
void CreateRenderPasses(const Device& device);
void CreateSampler(const Device& device);
void CreateShaders(const Device& device);
void CreateDescriptorPool(const Device& device);
@@ -33,7 +32,6 @@ private:
void CreatePipelineLayouts(const Device& device);
void CreatePipelines(const Device& device);
void UploadImages(const Device& device, Scheduler& scheduler);
void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index);
MemoryAllocator& m_memory_allocator;
@@ -54,17 +52,14 @@ private:
vk::ShaderModule m_rcas_shader;
vk::Pipeline m_easu_pipeline;
vk::Pipeline m_rcas_pipeline;
vk::RenderPass m_renderpass;
vk::Sampler m_sampler;
struct Images {
vk::DescriptorSets descriptor_sets;
std::array<vk::Image, MaxFsrStage> images;
std::array<vk::ImageView, MaxFsrStage> image_views;
std::array<vk::Framebuffer, MaxFsrStage> framebuffers;
};
std::vector<Images> m_dynamic_images;
bool m_images_ready{};
};
} // namespace Vulkan
@@ -21,7 +21,6 @@ FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
, m_image_count(u32(image_count))
{
CreateImages(device, allocator);
CreateRenderPasses(device);
CreateSampler(device);
CreateShaders(device);
CreateDescriptorPool(device);
@@ -41,15 +40,6 @@ void FXAA::CreateImages(const Device& device, MemoryAllocator& allocator) {
}
}
void FXAA::CreateRenderPasses(const Device& device) {
m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
for (auto& image : m_dynamic_images) {
image.framebuffer =
CreateWrappedFramebuffer(device, m_renderpass, image.image_view, m_extent);
}
}
void FXAA::CreateSampler(const Device& device) {
m_sampler = CreateWrappedSampler(device);
}
@@ -83,7 +73,7 @@ void FXAA::CreatePipelineLayouts(const Device& device) {
}
void FXAA::CreatePipelines(const Device& device) {
m_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout,
m_pipeline = CreateWrappedPipeline(device, VK_FORMAT_R16G16B16A16_SFLOAT, m_pipeline_layout,
std::tie(m_vertex_shader, m_fragment_shader));
}
@@ -99,44 +89,28 @@ void FXAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, si
device.GetLogical().UpdateDescriptorSets(updates, {});
}
void FXAA::UploadImages(const Device& device, Scheduler& scheduler) {
if (m_images_ready) {
return;
}
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
for (auto& image : m_dynamic_images) {
ClearColorImage(cmdbuf, *image.image);
}
});
scheduler.Finish();
m_images_ready = true;
}
void FXAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) {
const Image& image{m_dynamic_images[image_index]};
const VkImage input_image{*inout_image};
const VkImage output_image{*image.image};
const VkImageView output_view{*image.image_view};
const VkDescriptorSet descriptor_set{image.descriptor_sets[0]};
const VkFramebuffer framebuffer{*image.framebuffer};
const VkRenderPass renderpass{*m_renderpass};
const VkPipeline pipeline{*m_pipeline};
const VkPipelineLayout layout{*m_pipeline_layout};
const VkExtent2D extent{m_extent};
UploadImages(device, scheduler);
UpdateDescriptorSets(device, *inout_image_view, image_index);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([=](vk::CommandBuffer cmdbuf) {
TransitionImageLayout(cmdbuf, input_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, renderpass, framebuffer, extent);
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_UNDEFINED);
BeginRendering(cmdbuf, output_view, extent, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, {});
cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
});
@@ -25,7 +25,6 @@ public:
private:
void CreateImages(const Device& device, MemoryAllocator& allocator);
void CreateRenderPasses(const Device& device);
void CreateSampler(const Device& device);
void CreateShaders(const Device& device);
void CreateDescriptorPool(const Device& device);
@@ -34,11 +33,9 @@ private:
void CreatePipelineLayouts(const Device& device);
void CreatePipelines(const Device& device);
void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index);
void UploadImages(const Device& device, Scheduler& scheduler);
struct Image {
vk::DescriptorSets descriptor_sets{};
vk::Framebuffer framebuffer{};
vk::Image image{};
vk::ImageView image_view{};
};
@@ -51,9 +48,7 @@ private:
vk::DescriptorSetLayout m_descriptor_set_layout{};
vk::PipelineLayout m_pipeline_layout{};
vk::Pipeline m_pipeline{};
vk::RenderPass m_renderpass{};
vk::Sampler m_sampler{};
bool m_images_ready{};
};
} // namespace Vulkan
@@ -126,68 +126,7 @@ VkPrimitiveTopology ToTopology(reshadefx::primitive_topology topology) {
}
}
vk::RenderPass CreateFxRenderPass(const Device& device, VkFormat format, bool clear) {
VkAttachmentLoadOp load_op = VK_ATTACHMENT_LOAD_OP_LOAD;
VkImageLayout initial_layout = VK_IMAGE_LAYOUT_GENERAL;
if (clear) {
load_op = VK_ATTACHMENT_LOAD_OP_CLEAR;
initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
}
const VkAttachmentDescription2 attachment{
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
.pNext = nullptr,
.flags = 0,
.format = format,
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = load_op,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = initial_layout,
.finalLayout = VK_IMAGE_LAYOUT_GENERAL,
};
static constexpr VkAttachmentReference2 reference{
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
.pNext = nullptr,
.attachment = 0,
.layout = VK_IMAGE_LAYOUT_GENERAL,
.aspectMask = 0,
};
const VkSubpassDescription2 subpass{
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
.pNext = nullptr,
.flags = 0,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.viewMask = 0,
.inputAttachmentCount = 0,
.pInputAttachments = nullptr,
.colorAttachmentCount = 1,
.pColorAttachments = &reference,
.pResolveAttachments = nullptr,
.pDepthStencilAttachment = nullptr,
.preserveAttachmentCount = 0,
.pPreserveAttachments = nullptr,
};
return device.GetLogical().CreateRenderPass2(VkRenderPassCreateInfo2{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
.pNext = nullptr,
.flags = 0,
.attachmentCount = 1,
.pAttachments = &attachment,
.subpassCount = 1,
.pSubpasses = &subpass,
.dependencyCount = 0,
.pDependencies = nullptr,
.correlatedViewMaskCount = 0,
.pCorrelatedViewMasks = nullptr,
});
}
vk::Pipeline CreateFxPipeline(const Device& device, vk::RenderPass& renderpass,
vk::Pipeline CreateFxPipeline(const Device& device, VkFormat format,
vk::PipelineLayout& layout, VkShaderModule vertex_shader,
VkShaderModule fragment_shader,
const reshadefx::pass& pass) {
@@ -308,9 +247,10 @@ vk::Pipeline CreateFxPipeline(const Device& device, vk::RenderPass& renderpass,
.pDynamicStates = dynamic_states.data(),
};
const VkPipelineRenderingCreateInfo rendering_ci = ColorRenderingInfo(format);
return device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.pNext = &rendering_ci,
.flags = 0,
.stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(),
@@ -324,7 +264,7 @@ vk::Pipeline CreateFxPipeline(const Device& device, vk::RenderPass& renderpass,
.pColorBlendState = &color_blend,
.pDynamicState = &dynamic_state,
.layout = *layout,
.renderPass = *renderpass,
.renderPass = VK_NULL_HANDLE,
.subpass = 0,
.basePipelineHandle = nullptr,
.basePipelineIndex = 0,
@@ -540,7 +480,9 @@ bool PostProcessChain::BuildEffects(const Device& device, MemoryAllocator& alloc
for (const auto& pass : technique->passes) {
Pass out;
out.num_vertices = pass.num_vertices;
out.clear = pass.clear_render_targets != 0;
if (pass.clear_render_targets != 0) {
out.load_op = VK_ATTACHMENT_LOAD_OP_CLEAR;
}
out.target_texture = NO_TEXTURE;
out.extent = m_extent;
@@ -606,23 +548,9 @@ bool PostProcessChain::BuildEffects(const Device& device, MemoryAllocator& alloc
continue;
}
out.renderpass = CreateFxRenderPass(device, target_format, out.clear);
out.pipeline = CreateFxPipeline(device, out.renderpass, out.pipeline_layout,
out.pipeline = CreateFxPipeline(device, target_format, out.pipeline_layout,
*vertex_shader->second, *fragment_shader->second, pass);
if (out.writes_backbuffer) {
for (u32 image = 0; image < m_image_count; ++image) {
for (size_t slot = 0; slot < 2; ++slot) {
out.framebuffers.push_back(CreateWrappedFramebuffer(
device, out.renderpass, m_frames[image].views[slot], out.extent));
}
}
} else {
out.framebuffers.push_back(
CreateWrappedFramebuffer(device, out.renderpass,
effect.textures[out.target_texture].view, out.extent));
}
effect.passes.push_back(std::move(out));
}
@@ -859,19 +787,20 @@ void PostProcessChain::Draw(const Device& device, Scheduler& scheduler, size_t i
UpdateDescriptors(device, effect, pass, image_index, current_view);
VkFramebuffer framebuffer{};
VkImage target_image{};
VkImageView target_view{};
if (pass.writes_backbuffer) {
const u32 target_slot = (slot + 1) % 2;
framebuffer = *pass.framebuffers[image_index * 2 + target_slot];
target_image = *frame.images[target_slot];
target_view = *frame.views[target_slot];
} else {
framebuffer = *pass.framebuffers[0];
target_image = *effect.textures[pass.target_texture].image;
const Texture& texture = effect.textures[pass.target_texture];
target_image = *texture.image;
target_view = *texture.view;
}
const VkImage source_image = current_image;
const VkRenderPass renderpass = *pass.renderpass;
const VkAttachmentLoadOp load_op = pass.load_op;
const VkPipeline pipeline = *pass.pipeline;
const VkPipelineLayout layout = *pass.pipeline_layout;
const VkDescriptorSet uniform_set = effect.uniform_sets[image_index];
@@ -883,12 +812,12 @@ void PostProcessChain::Draw(const Device& device, Scheduler& scheduler, size_t i
scheduler.Record([=](vk::CommandBuffer cmdbuf) {
TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, target_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, renderpass, framebuffer, extent);
BeginRendering(cmdbuf, target_view, extent, load_op);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0,
std::array{uniform_set, sampler_set}, {});
cmdbuf.Draw(vertices, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, target_image, VK_IMAGE_LAYOUT_GENERAL);
});
@@ -77,17 +77,15 @@ private:
};
struct Pass {
vk::RenderPass renderpass{};
vk::Pipeline pipeline{};
vk::DescriptorSetLayout sampler_layout{};
vk::PipelineLayout pipeline_layout{};
vk::DescriptorSets sampler_sets{};
std::vector<SamplerBinding> sampler_bindings{};
std::vector<vk::Framebuffer> framebuffers{};
size_t target_texture{};
VkExtent2D extent{};
u32 num_vertices{3};
bool clear{};
VkAttachmentLoadOp load_op{VK_ATTACHMENT_LOAD_OP_LOAD};
bool writes_backbuffer{};
};
@@ -34,10 +34,6 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image
images.image_view = CreateWrappedImageView(device, images.image, VK_FORMAT_R16G16B16A16_SFLOAT);
}
m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
for (auto& images : m_dynamic_images)
images.framebuffer = CreateWrappedFramebuffer(device, m_renderpass, images.image_view, m_extent);
m_sampler = CreateBilinearSampler(device);
m_vert_shader = BuildShader(device, SGSR1_SHADER_VERT_SPV);
m_stage_shader = m_edge_dir
@@ -66,7 +62,9 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image
.pPushConstantRanges = &range,
};
m_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci);
m_stage_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader));
m_stage_pipeline = CreateWrappedPipeline(device, VK_FORMAT_R16G16B16A16_SFLOAT,
m_pipeline_layout,
std::tie(m_vert_shader, m_stage_shader));
}
void SGSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) {
@@ -78,26 +76,14 @@ void SGSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, si
device.GetLogical().UpdateDescriptorSets(updates, {});
}
void SGSR::UploadImages(const Device& device, Scheduler& scheduler) {
if (!m_images_ready) {
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
for (auto& image : m_dynamic_images)
ClearColorImage(cmdbuf, *image.image);
});
scheduler.Finish();
m_images_ready = true;
}
}
VkImageView SGSR::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle<f32>& crop_rect) {
Images& images = m_dynamic_images[image_index];
auto const output_image = *images.image;
auto const output_view = *images.image_view;
auto const descriptor_set = images.descriptor_sets[0];
auto const framebuffer = *images.framebuffer;
auto const pipeline = *m_stage_pipeline;
VkPipelineLayout layout = *m_pipeline_layout;
VkRenderPass renderpass = *m_renderpass;
VkExtent2D extent = m_extent;
const f32 input_image_width = f32(input_image_extent.width);
@@ -125,19 +111,19 @@ VkImageView SGSR::Draw(const Device& device, Scheduler& scheduler, size_t image_
viewport_con[7] = std::bit_cast<u32>((std::min)(crop_rect.top, crop_rect.bottom));
viewport_con[8] = std::bit_cast<u32>(edge_sharpness);
UploadImages(device, scheduler);
UpdateDescriptorSets(device, source_image_view, image_index);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([=](vk::CommandBuffer cmdbuf) {
TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, renderpass, framebuffer, extent);
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_UNDEFINED);
BeginRendering(cmdbuf, output_view, extent, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, {});
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, viewport_con);
cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
});
return *images.image_view;
@@ -19,7 +19,6 @@ public:
VkImageView Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle<f32>& crop_rect);
private:
void Initialize(const Device& device);
void UploadImages(const Device& device, Scheduler& scheduler);
void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index);
MemoryAllocator& m_memory_allocator;
@@ -32,17 +31,14 @@ private:
vk::ShaderModule m_vert_shader;
vk::ShaderModule m_stage_shader;
vk::Pipeline m_stage_pipeline;
vk::RenderPass m_renderpass;
vk::Sampler m_sampler;
struct Images {
vk::DescriptorSets descriptor_sets;
vk::Image image;
vk::ImageView image_view;
vk::Framebuffer framebuffer;
};
std::vector<Images> m_dynamic_images;
bool m_images_ready{};
bool m_edge_dir{};
};
+21 -47
View File
@@ -32,7 +32,6 @@ SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
, m_image_count(u32(image_count))
{
CreateImages(device);
CreateRenderPasses(device);
CreateSampler(device);
CreateShaders(device);
CreateDescriptorPool(device);
@@ -74,26 +73,6 @@ void SMAA::CreateImages(const Device& device) {
}
}
void SMAA::CreateRenderPasses(const Device& device) {
m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(device, VK_FORMAT_R16G16_SFLOAT);
m_renderpasses[BlendingWeightCalculation] =
CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
m_renderpasses[NeighborhoodBlending] =
CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
for (auto& images : m_dynamic_images) {
images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer(
device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent);
images.framebuffers[BlendingWeightCalculation] =
CreateWrappedFramebuffer(device, m_renderpasses[BlendingWeightCalculation],
images.image_views[Blend], m_extent);
images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer(
device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent);
}
}
void SMAA::CreateSampler(const Device& device) {
m_sampler = CreateWrappedSampler(device);
}
@@ -155,9 +134,14 @@ void SMAA::CreatePipelineLayouts(const Device& device) {
}
void SMAA::CreatePipelines(const Device& device) {
static constexpr std::array<VkFormat, MaxSMAAStage> formats{
VK_FORMAT_R16G16_SFLOAT,
VK_FORMAT_R16G16B16A16_SFLOAT,
VK_FORMAT_R16G16B16A16_SFLOAT,
};
for (size_t i = 0; i < MaxSMAAStage; i++) {
m_pipelines[i] =
CreateWrappedPipeline(device, m_renderpasses[i], m_pipeline_layouts[i],
CreateWrappedPipeline(device, formats[i], m_pipeline_layouts[i],
std::tie(m_vertex_shaders[i], m_fragment_shaders[i]));
}
}
@@ -202,15 +186,6 @@ void SMAA::UploadImages(const Device& device, Scheduler& scheduler) {
UploadImage(device, m_allocator, scheduler, m_static_images[Search], search_extent,
VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes));
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
for (auto& images : m_dynamic_images) {
for (size_t i = 0; i < MaxDynamicImage; i++) {
ClearColorImage(cmdbuf, *images.images[i]);
}
}
});
scheduler.Finish();
m_images_ready = true;
}
@@ -228,10 +203,9 @@ void SMAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index,
VkDescriptorSet neighborhood_blending_descriptor_set =
images.descriptor_sets[NeighborhoodBlending];
VkFramebuffer edge_detection_framebuffer = *images.framebuffers[EdgeDetection];
VkFramebuffer blending_weight_calculation_framebuffer =
*images.framebuffers[BlendingWeightCalculation];
VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending];
VkImageView edges_view = *images.image_views[Edges];
VkImageView blend_view = *images.image_views[Blend];
VkImageView output_view = *images.image_views[Output];
UploadImages(device, scheduler);
UpdateDescriptorSets(device, *inout_image_view, image_index);
@@ -239,38 +213,38 @@ void SMAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index,
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([=, this](vk::CommandBuffer cmdbuf) {
TransitionImageLayout(cmdbuf, input_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, *m_renderpasses[EdgeDetection], edge_detection_framebuffer,
m_extent);
TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_UNDEFINED);
BeginRendering(cmdbuf, edges_view, m_extent, VK_ATTACHMENT_LOAD_OP_CLEAR);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[EdgeDetection]);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
*m_pipeline_layouts[EdgeDetection], 0,
edge_detection_descriptor_set, {});
cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, *m_renderpasses[BlendingWeightCalculation],
blending_weight_calculation_framebuffer, m_extent);
TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_UNDEFINED);
BeginRendering(cmdbuf, blend_view, m_extent, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
*m_pipelines[BlendingWeightCalculation]);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
*m_pipeline_layouts[BlendingWeightCalculation], 0,
blending_weight_calculation_descriptor_set, {});
cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, blend_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, *m_renderpasses[NeighborhoodBlending],
neighborhood_blending_framebuffer, m_extent);
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_UNDEFINED);
BeginRendering(cmdbuf, output_view, m_extent, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelines[NeighborhoodBlending]);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
*m_pipeline_layouts[NeighborhoodBlending], 0,
neighborhood_blending_descriptor_set, {});
cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
});
@@ -47,7 +47,6 @@ private:
};
void CreateImages(const Device& device);
void CreateRenderPasses(const Device& device);
void CreateSampler(const Device& device);
void CreateShaders(const Device& device);
void CreateDescriptorPool(const Device& device);
@@ -68,7 +67,6 @@ private:
std::array<vk::ShaderModule, MaxSMAAStage> m_vertex_shaders{};
std::array<vk::ShaderModule, MaxSMAAStage> m_fragment_shaders{};
std::array<vk::Pipeline, MaxSMAAStage> m_pipelines{};
std::array<vk::RenderPass, MaxSMAAStage> m_renderpasses{};
std::array<vk::Image, MaxStaticImage> m_static_images{};
std::array<vk::ImageView, MaxStaticImage> m_static_image_views{};
@@ -77,7 +75,6 @@ private:
vk::DescriptorSets descriptor_sets{};
std::array<vk::Image, MaxDynamicImage> images{};
std::array<vk::ImageView, MaxDynamicImage> image_views{};
std::array<vk::Framebuffer, MaxSMAAStage> framebuffers{};
};
std::vector<Images> m_dynamic_images{};
bool m_images_ready{};
+46 -113
View File
@@ -198,100 +198,6 @@ vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkF
});
}
vk::RenderPass CreateWrappedRenderPass(const Device& device, VkFormat format,
VkImageLayout initial_layout) {
const VkAttachmentDescription2 attachment{
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
.pNext = nullptr,
.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT,
.format = format,
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = initial_layout == VK_IMAGE_LAYOUT_UNDEFINED ? VK_ATTACHMENT_LOAD_OP_DONT_CARE
: VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
.initialLayout = initial_layout,
.finalLayout = VK_IMAGE_LAYOUT_GENERAL,
};
static constexpr VkAttachmentReference2 color_attachment_ref{
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
.pNext = nullptr,
.attachment = 0,
.layout = VK_IMAGE_LAYOUT_GENERAL,
.aspectMask = 0,
};
const VkSubpassDescription2 subpass_description{
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
.pNext = nullptr,
.flags = 0,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.viewMask = 0,
.inputAttachmentCount = 0,
.pInputAttachments = nullptr,
.colorAttachmentCount = 1,
.pColorAttachments = &color_attachment_ref,
.pResolveAttachments = nullptr,
.pDepthStencilAttachment = nullptr,
.preserveAttachmentCount = 0,
.pPreserveAttachments = nullptr,
};
static constexpr VkMemoryBarrier2 dependency_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccessMask = 0,
.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstAccessMask =
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
};
static constexpr VkSubpassDependency2 dependency{
.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
.pNext = &dependency_barrier,
.srcSubpass = VK_SUBPASS_EXTERNAL,
.dstSubpass = 0,
.srcStageMask = 0,
.dstStageMask = 0,
.srcAccessMask = 0,
.dstAccessMask = 0,
.dependencyFlags = 0,
.viewOffset = 0,
};
return device.GetLogical().CreateRenderPass2(VkRenderPassCreateInfo2{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
.pNext = nullptr,
.flags = 0,
.attachmentCount = 1,
.pAttachments = &attachment,
.subpassCount = 1,
.pSubpasses = &subpass_description,
.dependencyCount = 1,
.pDependencies = &dependency,
.correlatedViewMaskCount = 0,
.pCorrelatedViewMasks = nullptr,
});
}
vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& render_pass,
vk::ImageView& dest_image, VkExtent2D extent) {
return device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.renderPass = *render_pass,
.attachmentCount = 1,
.pAttachments = dest_image.address(),
.width = extent.width,
.height = extent.height,
.layers = 1,
});
}
vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter) {
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
@@ -422,8 +328,20 @@ vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device,
});
}
VkPipelineRenderingCreateInfo ColorRenderingInfo(const VkFormat& format) {
return {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.pNext = nullptr,
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &format,
.depthAttachmentFormat = VK_FORMAT_UNDEFINED,
.stencilAttachmentFormat = VK_FORMAT_UNDEFINED,
};
}
static vk::Pipeline CreateWrappedPipelineImpl(
const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout,
const Device& device, VkFormat format, vk::PipelineLayout& layout,
std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders,
VkPipelineColorBlendAttachmentState blending) {
const std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages{{
@@ -527,9 +445,10 @@ static vk::Pipeline CreateWrappedPipelineImpl(
.pDynamicStates = dynamic_states.data(),
};
const VkPipelineRenderingCreateInfo rendering_ci = ColorRenderingInfo(format);
return device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.pNext = &rendering_ci,
.flags = 0,
.stageCount = static_cast<u32>(shader_stages.size()),
.pStages = shader_stages.data(),
@@ -543,14 +462,14 @@ static vk::Pipeline CreateWrappedPipelineImpl(
.pColorBlendState = &color_blend_ci,
.pDynamicState = &dynamic_state_ci,
.layout = *layout,
.renderPass = *renderpass,
.renderPass = VK_NULL_HANDLE,
.subpass = 0,
.basePipelineHandle = 0,
.basePipelineIndex = 0,
});
}
vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass,
vk::Pipeline CreateWrappedPipeline(const Device& device, VkFormat format,
vk::PipelineLayout& layout,
std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders) {
constexpr VkPipelineColorBlendAttachmentState color_blend_attachment_disabled{
@@ -565,12 +484,12 @@ vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderp
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
return CreateWrappedPipelineImpl(device, renderpass, layout, shaders,
return CreateWrappedPipelineImpl(device, format, layout, shaders,
color_blend_attachment_disabled);
}
vk::Pipeline CreateWrappedPremultipliedBlendingPipeline(
const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout,
const Device& device, VkFormat format, vk::PipelineLayout& layout,
std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders) {
constexpr VkPipelineColorBlendAttachmentState color_blend_attachment_premultiplied{
.blendEnable = VK_TRUE,
@@ -584,12 +503,12 @@ vk::Pipeline CreateWrappedPremultipliedBlendingPipeline(
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
return CreateWrappedPipelineImpl(device, renderpass, layout, shaders,
return CreateWrappedPipelineImpl(device, format, layout, shaders,
color_blend_attachment_premultiplied);
}
vk::Pipeline CreateWrappedCoverageBlendingPipeline(
const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout,
const Device& device, VkFormat format, vk::PipelineLayout& layout,
std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders) {
constexpr VkPipelineColorBlendAttachmentState color_blend_attachment_coverage{
.blendEnable = VK_TRUE,
@@ -603,7 +522,7 @@ vk::Pipeline CreateWrappedCoverageBlendingPipeline(
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
return CreateWrappedPipelineImpl(device, renderpass, layout, shaders,
return CreateWrappedPipelineImpl(device, format, layout, shaders,
color_blend_attachment_coverage);
}
@@ -725,21 +644,35 @@ void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image) {
cmdbuf.ClearColorImage(image, VK_IMAGE_LAYOUT_GENERAL, {}, subresources);
}
void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer,
VkExtent2D extent) {
const VkRenderPassBeginInfo renderpass_bi{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
void BeginRendering(vk::CommandBuffer& cmdbuf, VkImageView view, VkExtent2D extent,
VkAttachmentLoadOp load_op, const VkClearValue& clear_value) {
const VkRenderingAttachmentInfo attachment{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.renderPass = render_pass,
.framebuffer = framebuffer,
.imageView = view,
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = load_op,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = clear_value,
};
cmdbuf.BeginRendering(VkRenderingInfo{
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.pNext = nullptr,
.flags = 0,
.renderArea{
.offset{},
.extent = extent,
},
.clearValueCount = 0,
.pClearValues = nullptr,
};
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
.layerCount = 1,
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachments = &attachment,
.pDepthAttachment = nullptr,
.pStencilAttachment = nullptr,
});
const VkViewport viewport{
.x = 0.0f,
@@ -27,10 +27,6 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe
void ClearColorImage(vk::CommandBuffer& cmdbuf, VkImage image);
vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format);
vk::RenderPass CreateWrappedRenderPass(const Device& device, VkFormat format,
VkImageLayout initial_layout = VK_IMAGE_LAYOUT_GENERAL);
vk::Framebuffer CreateWrappedFramebuffer(const Device& device, vk::RenderPass& render_pass,
vk::ImageView& dest_image, VkExtent2D extent);
vk::Sampler CreateWrappedSampler(const Device& device, VkFilter filter = VK_FILTER_LINEAR);
vk::ShaderModule CreateWrappedShaderModule(const Device& device, std::span<const u32> code);
vk::DescriptorPool CreateWrappedDescriptorPool(const Device& device, size_t max_descriptors,
@@ -47,16 +43,17 @@ vk::DescriptorSets CreateWrappedDescriptorSets(vk::DescriptorPool& pool,
vk::Span<VkDescriptorSetLayout> layouts);
vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device,
vk::DescriptorSetLayout& layout);
vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass,
[[nodiscard]] VkPipelineRenderingCreateInfo ColorRenderingInfo(const VkFormat& format);
vk::Pipeline CreateWrappedPipeline(const Device& device, VkFormat format,
vk::PipelineLayout& layout,
std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders);
vk::Pipeline CreateWrappedComputePipeline(const Device& device, vk::PipelineLayout& layout,
VkShaderModule shader);
vk::Pipeline CreateWrappedPremultipliedBlendingPipeline(
const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout,
const Device& device, VkFormat format, vk::PipelineLayout& layout,
std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders);
vk::Pipeline CreateWrappedCoverageBlendingPipeline(
const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout,
const Device& device, VkFormat format, vk::PipelineLayout& layout,
std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders);
VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images,
VkSampler sampler, VkImageView view,
@@ -65,7 +62,7 @@ vk::Sampler CreateBilinearSampler(const Device& device);
vk::Sampler CreateNearestNeighborSampler(const Device& device);
vk::Sampler CreateCubicSampler(const Device& device, VkCubicFilterWeightsQCOM qcom_weights);
void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer,
VkExtent2D extent);
void BeginRendering(vk::CommandBuffer& cmdbuf, VkImageView view, VkExtent2D extent,
VkAttachmentLoadOp load_op, const VkClearValue& clear_value = {});
} // namespace Vulkan
@@ -25,8 +25,7 @@ WindowAdaptPass::WindowAdaptPass(const Device& device, VkFormat frame_format, vk
CreateDescriptorSetLayout(device);
CreatePipelineLayout(device);
CreateVertexShader(device);
CreateRenderPass(device, frame_format);
CreatePipelines(device);
CreatePipelines(device, frame_format);
}
WindowAdaptPass::~WindowAdaptPass() = default;
@@ -36,8 +35,8 @@ void WindowAdaptPass::Draw(const Device& device, RasterizerVulkan& rasterizer, S
std::span<const Tegra::FramebufferConfig> configs,
const Layout::FramebufferLayout& layout, Frame* dst) {
const VkFramebuffer host_framebuffer{*dst->framebuffer};
const VkRenderPass renderpass{*render_pass};
const VkImage host_image{*dst->image};
const VkImageView host_view{*dst->image_view};
const VkPipelineLayout graphics_pipeline_layout{*pipeline_layout};
const VkExtent2D render_area{
.width = dst->width,
@@ -73,26 +72,13 @@ void WindowAdaptPass::Draw(const Device& device, RasterizerVulkan& rasterizer, S
const f32 bg_red = Settings::values.bg_red.GetValue() / 255.0f;
const f32 bg_green = Settings::values.bg_green.GetValue() / 255.0f;
const f32 bg_blue = Settings::values.bg_blue.GetValue() / 255.0f;
const VkClearAttachment clear_attachment{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.colorAttachment = 0,
.clearValue =
{
.color = {.float32 = {bg_red, bg_green, bg_blue, 1.0f}},
},
};
const VkClearRect clear_rect{
.rect =
{
.offset = {0, 0},
.extent = render_area,
},
.baseArrayLayer = 0,
.layerCount = 1,
const VkClearValue clear_value{
.color = {.float32 = {bg_red, bg_green, bg_blue, 1.0f}},
};
BeginRenderPass(cmdbuf, renderpass, host_framebuffer, render_area);
cmdbuf.ClearAttachments({clear_attachment}, {clear_rect});
TransitionImageLayout(cmdbuf, host_image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_UNDEFINED);
BeginRendering(cmdbuf, host_view, render_area, VK_ATTACHMENT_LOAD_OP_CLEAR, clear_value);
for (size_t i = 0; i < layer_count; i++) {
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipelines[i]);
@@ -103,7 +89,7 @@ void WindowAdaptPass::Draw(const Device& device, RasterizerVulkan& rasterizer, S
cmdbuf.Draw(4, 1, 0, 0);
}
cmdbuf.EndRenderPass();
cmdbuf.EndRendering();
});
}
@@ -111,10 +97,6 @@ VkDescriptorSetLayout WindowAdaptPass::GetDescriptorSetLayout() {
return *descriptor_set_layout;
}
VkRenderPass WindowAdaptPass::GetRenderPass() {
return *render_pass;
}
void WindowAdaptPass::CreateDescriptorSetLayout(const Device& device) {
descriptor_set_layout =
CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
@@ -142,17 +124,13 @@ void WindowAdaptPass::CreateVertexShader(const Device& device) {
vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV);
}
void WindowAdaptPass::CreateRenderPass(const Device& device, VkFormat frame_format) {
render_pass = CreateWrappedRenderPass(device, frame_format, VK_IMAGE_LAYOUT_UNDEFINED);
}
void WindowAdaptPass::CreatePipelines(const Device& device) {
opaque_pipeline = CreateWrappedPipeline(device, render_pass, pipeline_layout,
void WindowAdaptPass::CreatePipelines(const Device& device, VkFormat frame_format) {
opaque_pipeline = CreateWrappedPipeline(device, frame_format, pipeline_layout,
std::tie(vertex_shader, fragment_shader));
premultiplied_pipeline = CreateWrappedPremultipliedBlendingPipeline(
device, render_pass, pipeline_layout, std::tie(vertex_shader, fragment_shader));
device, frame_format, pipeline_layout, std::tie(vertex_shader, fragment_shader));
coverage_pipeline = CreateWrappedCoverageBlendingPipeline(
device, render_pass, pipeline_layout, std::tie(vertex_shader, fragment_shader));
device, frame_format, pipeline_layout, std::tie(vertex_shader, fragment_shader));
}
} // namespace Vulkan
@@ -38,21 +38,18 @@ public:
const Layout::FramebufferLayout& layout, Frame* dst);
VkDescriptorSetLayout GetDescriptorSetLayout();
VkRenderPass GetRenderPass();
private:
void CreateDescriptorSetLayout(const Device& device);
void CreatePipelineLayout(const Device& device);
void CreateVertexShader(const Device& device);
void CreateRenderPass(const Device& device, VkFormat frame_format);
void CreatePipelines(const Device& device);
void CreatePipelines(const Device& device, VkFormat frame_format);
vk::DescriptorSetLayout descriptor_set_layout;
vk::PipelineLayout pipeline_layout;
vk::Sampler sampler;
vk::ShaderModule vertex_shader;
vk::ShaderModule fragment_shader;
vk::RenderPass render_pass;
vk::Pipeline opaque_pipeline;
vk::Pipeline premultiplied_pipeline;
vk::Pipeline coverage_pipeline;
@@ -275,7 +275,6 @@ vk::Buffer RendererVulkan::RenderToBuffer(std::span<const Tegra::FramebufferConf
f.image =
CreateWrappedImage(memory_allocator, VkExtent2D{layout.width, layout.height}, format);
f.image_view = CreateWrappedImageView(device, f.image, format);
f.framebuffer = blit_capture.CreateFramebuffer(device, layout, *f.image_view, format);
return f;
}();
@@ -353,8 +352,6 @@ void RendererVulkan::RenderAppletCaptureLayer(
if (!applet_frame.image) {
applet_frame.image = CreateWrappedImage(memory_allocator, CaptureImageSize, CaptureFormat);
applet_frame.image_view = CreateWrappedImageView(device, applet_frame.image, CaptureFormat);
applet_frame.framebuffer = blit_applet.CreateFramebuffer(device,
VideoCore::Capture::Layout, *applet_frame.image_view, CaptureFormat);
}
scheduler.RequestOutsideRenderPassOperationContext();
@@ -98,8 +98,7 @@ void BlitScreen::PrepareFrame(const Device& device, Frame* frame,
return;
}
present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format,
window_adapt->GetRenderPass(), true);
present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format, true);
}
void BlitScreen::DrawToFrame(const Device& device, RasterizerVulkan& rasterizer, Frame* frame,
@@ -133,13 +132,13 @@ void BlitScreen::DrawToFrame(const Device& device, RasterizerVulkan& rasterizer,
if (presentation_recreate_required) {
present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format,
window_adapt->GetRenderPass(), storage_required);
storage_required);
}
image_index = 0;
} else if (present_manager.NeedsStorage(frame, storage_required)) {
present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format,
window_adapt->GetRenderPass(), true);
true);
}
const VkExtent2D window_size{
@@ -162,39 +161,4 @@ void BlitScreen::DrawToFrame(const Device& device, RasterizerVulkan& rasterizer,
}
}
vk::Framebuffer BlitScreen::CreateFramebuffer(const Device& device, const Layout::FramebufferLayout& layout,
VkImageView image_view,
VkFormat current_view_format) {
bool format_updated = swapchain_view_format != current_view_format;
swapchain_view_format = current_view_format;
if (!window_adapt || scaling_filter != filters.get_scaling_filter() || format_updated) {
WaitIdle(device);
SetWindowAdaptPass(device);
image_index = 0;
}
const VkExtent2D extent{
.width = layout.width,
.height = layout.height,
};
return CreateFramebuffer(device, image_view, extent, window_adapt->GetRenderPass());
}
vk::Framebuffer BlitScreen::CreateFramebuffer(const Device& device, const VkImageView& image_view, VkExtent2D extent,
VkRenderPass render_pass) {
return device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.renderPass = render_pass,
.attachmentCount = 1,
.pAttachments = &image_view,
.width = extent.width,
.height = extent.height,
.layers = 1,
});
}
} // namespace Vulkan
@@ -62,15 +62,9 @@ public:
void PrepareFrame(const Device& device, Frame* frame, const Layout::FramebufferLayout& layout);
[[nodiscard]] vk::Framebuffer CreateFramebuffer(const Device& device, const Layout::FramebufferLayout& layout,
VkImageView image_view,
VkFormat current_view_format);
private:
void WaitIdle(const Device& device);
void SetWindowAdaptPass(const Device& device);
vk::Framebuffer CreateFramebuffer(const Device& device, const VkImageView& image_view, VkExtent2D extent,
VkRenderPass render_pass);
Tegra::MaxwellDeviceMemoryManager& device_memory;
MemoryAllocator& memory_allocator;
@@ -209,7 +209,7 @@ bool PresentManager::NeedsStorage(const Frame* frame, bool required) const {
}
void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format,
VkRenderPass rd, bool storage) {
bool storage) {
auto& dld = device.GetLogical();
frame->width = width;
@@ -295,19 +295,6 @@ void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat
},
});
}
const VkImageView image_view{*frame->image_view};
frame->framebuffer = dld.CreateFramebuffer({
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.renderPass = rd,
.attachmentCount = 1,
.pAttachments = &image_view,
.width = width,
.height = height,
.layers = 1,
});
}
void PresentManager::WaitPresent() {
@@ -33,7 +33,6 @@ struct Frame {
vk::Image image;
vk::ImageView image_view;
vk::ImageView storage_view;
vk::Framebuffer framebuffer;
vk::CommandBuffer cmdbuf;
vk::Semaphore render_ready;
vk::Fence present_done;
@@ -59,7 +58,7 @@ public:
/// Recreates the present frame to match the provided parameters
void RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format,
VkRenderPass rd, bool storage);
bool storage);
[[nodiscard]] bool NeedsStorage(const Frame* frame, bool required) const;
@@ -1423,8 +1423,7 @@ void Device::RemoveUnsuitableExtensions() {
extensions.synchronization2 = features.synchronization2.synchronization2;
extensions.dynamic_rendering = features.dynamic_rendering.dynamicRendering;
if (!extensions.synchronization2 || !extensions.dynamic_rendering ||
!IsKhrCreateRenderPass2Supported()) {
if (!extensions.synchronization2 || !extensions.dynamic_rendering) {
throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT);
}
}
@@ -637,11 +637,6 @@ FN_MAX_LIMIT_LIST
return extensions.shader_stencil_export;
}
/// Returns true if the device supports VK_KHR_create_renderpass2.
bool IsKhrCreateRenderPass2Supported() const {
return extensions.create_renderpass2 || instance_version >= VK_API_VERSION_1_2;
}
/// Returns true if the device supports VK_KHR_depth_stencil_resolve.
bool IsKhrDepthStencilResolveSupported() const {
return extensions.depth_stencil_resolve || instance_version >= VK_API_VERSION_1_2;
@@ -88,7 +88,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkBeginCommandBuffer);
X(vkCmdBeginConditionalRenderingEXT);
X(vkCmdBeginQuery);
X(vkCmdBeginRenderPass);
X(vkCmdBeginRendering);
X(vkCmdBeginTransformFeedbackEXT);
X(vkCmdBindDescriptorSets);
@@ -116,7 +115,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdDrawIndirectByteCountEXT);
X(vkCmdEndConditionalRenderingEXT);
X(vkCmdEndQuery);
X(vkCmdEndRenderPass);
X(vkCmdEndRendering);
X(vkCmdEndTransformFeedbackEXT);
X(vkCmdFillBuffer);
@@ -169,13 +167,11 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCreateDescriptorSetLayout);
X(vkCreateDescriptorUpdateTemplate);
X(vkCreateFence);
X(vkCreateFramebuffer);
X(vkCreateGraphicsPipelines);
X(vkCreateImageView);
X(vkCreatePipelineCache);
X(vkCreatePipelineLayout);
X(vkCreateQueryPool);
X(vkCreateRenderPass2);
X(vkCreateSampler);
X(vkCreateSemaphore);
X(vkCreateShaderModule);
@@ -187,14 +183,12 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkDestroyDescriptorSetLayout);
X(vkDestroyDescriptorUpdateTemplate);
X(vkDestroyFence);
X(vkDestroyFramebuffer);
X(vkDestroyImage);
X(vkDestroyImageView);
X(vkDestroyPipeline);
X(vkDestroyPipelineCache);
X(vkDestroyPipelineLayout);
X(vkDestroyQueryPool);
X(vkDestroyRenderPass);
X(vkDestroySampler);
X(vkDestroySemaphore);
X(vkDestroyShaderModule);
@@ -265,10 +259,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
if (!dld.vkCmdEndRendering) {
Proc(dld.vkCmdEndRendering, dld, "vkCmdEndRenderingKHR", device);
}
if (!dld.vkCreateRenderPass2) {
Proc(dld.vkCreateRenderPass2, dld, "vkCreateRenderPass2KHR", device);
}
#undef X
}
@@ -363,10 +353,6 @@ void Destroy(VkDevice device, VkFence handle, const DeviceDispatch& dld) noexcep
dld.vkDestroyFence(device, handle, nullptr);
}
void Destroy(VkDevice device, VkFramebuffer handle, const DeviceDispatch& dld) noexcept {
dld.vkDestroyFramebuffer(device, handle, nullptr);
}
void Destroy(VkDevice device, VkImage handle, const DeviceDispatch& dld) noexcept {
dld.vkDestroyImage(device, handle, nullptr);
}
@@ -391,10 +377,6 @@ void Destroy(VkDevice device, VkQueryPool handle, const DeviceDispatch& dld) noe
dld.vkDestroyQueryPool(device, handle, nullptr);
}
void Destroy(VkDevice device, VkRenderPass handle, const DeviceDispatch& dld) noexcept {
dld.vkDestroyRenderPass(device, handle, nullptr);
}
void Destroy(VkDevice device, VkSampler handle, const DeviceDispatch& dld) noexcept {
dld.vkDestroySampler(device, handle, nullptr);
}
@@ -529,10 +511,6 @@ void Fence::SetObjectNameEXT(const char* name) const {
SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_FENCE, name);
}
void Framebuffer::SetObjectNameEXT(const char* name) const {
SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_FRAMEBUFFER, name);
}
DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) const {
const std::size_t num = ai.descriptorSetCount;
std::unique_ptr sets = std::make_unique<VkDescriptorSet[]>(num);
@@ -662,12 +640,6 @@ DescriptorPool Device::CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci
return DescriptorPool(object, handle, *dld);
}
RenderPass Device::CreateRenderPass2(const VkRenderPassCreateInfo2& ci) const {
VkRenderPass object;
Check(dld->vkCreateRenderPass2(handle, &ci, nullptr, &object));
return RenderPass(object, handle, *dld);
}
DescriptorSetLayout Device::CreateDescriptorSetLayout(
const VkDescriptorSetLayoutCreateInfo& ci) const {
VkDescriptorSetLayout object;
@@ -712,12 +684,6 @@ Sampler Device::CreateSampler(const VkSamplerCreateInfo& ci) const {
return Sampler(object, handle, *dld);
}
Framebuffer Device::CreateFramebuffer(const VkFramebufferCreateInfo& ci) const {
VkFramebuffer object;
Check(dld->vkCreateFramebuffer(handle, &ci, nullptr, &object));
return Framebuffer(object, handle, *dld);
}
CommandPool Device::CreateCommandPool(const VkCommandPoolCreateInfo& ci) const {
VkCommandPool object;
Check(dld->vkCreateCommandPool(handle, &ci, nullptr, &object));
@@ -237,7 +237,6 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkBeginCommandBuffer vkBeginCommandBuffer{};
PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT{};
PFN_vkCmdBeginQuery vkCmdBeginQuery{};
PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass{};
PFN_vkCmdBeginRendering vkCmdBeginRendering{};
PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT{};
PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets{};
@@ -266,7 +265,6 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT{};
PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT{};
PFN_vkCmdEndQuery vkCmdEndQuery{};
PFN_vkCmdEndRenderPass vkCmdEndRenderPass{};
PFN_vkCmdEndRendering vkCmdEndRendering{};
PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{};
PFN_vkCmdFillBuffer vkCmdFillBuffer{};
@@ -318,13 +316,11 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout{};
PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate{};
PFN_vkCreateFence vkCreateFence{};
PFN_vkCreateFramebuffer vkCreateFramebuffer{};
PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines{};
PFN_vkCreateImageView vkCreateImageView{};
PFN_vkCreatePipelineCache vkCreatePipelineCache{};
PFN_vkCreatePipelineLayout vkCreatePipelineLayout{};
PFN_vkCreateQueryPool vkCreateQueryPool{};
PFN_vkCreateRenderPass2 vkCreateRenderPass2{};
PFN_vkCreateSampler vkCreateSampler{};
PFN_vkCreateSemaphore vkCreateSemaphore{};
PFN_vkCreateShaderModule vkCreateShaderModule{};
@@ -336,14 +332,12 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout{};
PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate{};
PFN_vkDestroyFence vkDestroyFence{};
PFN_vkDestroyFramebuffer vkDestroyFramebuffer{};
PFN_vkDestroyImage vkDestroyImage{};
PFN_vkDestroyImageView vkDestroyImageView{};
PFN_vkDestroyPipeline vkDestroyPipeline{};
PFN_vkDestroyPipelineCache vkDestroyPipelineCache{};
PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout{};
PFN_vkDestroyQueryPool vkDestroyQueryPool{};
PFN_vkDestroyRenderPass vkDestroyRenderPass{};
PFN_vkDestroySampler vkDestroySampler{};
PFN_vkDestroySemaphore vkDestroySemaphore{};
PFN_vkDestroyShaderModule vkDestroyShaderModule{};
@@ -396,14 +390,12 @@ void Destroy(VkDevice, VkDescriptorPool, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkDescriptorSetLayout, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkDescriptorUpdateTemplate, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkFence, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkFramebuffer, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkImageView, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkPipeline, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkPipelineCache, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkPipelineLayout, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkQueryPool, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkRenderPass, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkSampler, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkSwapchainKHR, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkSemaphore, const DeviceDispatch&) noexcept;
@@ -651,7 +643,6 @@ using DescriptorUpdateTemplate = Handle<VkDescriptorUpdateTemplate, VkDevice, De
using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>;
using PipelineLayout = Handle<VkPipelineLayout, VkDevice, DeviceDispatch>;
using QueryPool = Handle<VkQueryPool, VkDevice, DeviceDispatch>;
using RenderPass = Handle<VkRenderPass, VkDevice, DeviceDispatch>;
using Sampler = Handle<VkSampler, VkDevice, DeviceDispatch>;
using SurfaceKHR = Handle<VkSurfaceKHR, VkInstance, InstanceDispatch>;
@@ -905,14 +896,6 @@ public:
}
};
class Framebuffer : public Handle<VkFramebuffer, VkDevice, DeviceDispatch> {
using Handle<VkFramebuffer, VkDevice, DeviceDispatch>::Handle;
public:
/// Set object name.
void SetObjectNameEXT(const char* name) const;
};
class DescriptorPool : public Handle<VkDescriptorPool, VkDevice, DeviceDispatch> {
using Handle<VkDescriptorPool, VkDevice, DeviceDispatch>::Handle;
@@ -1025,8 +1008,6 @@ public:
[[nodiscard]] DescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const;
[[nodiscard]] RenderPass CreateRenderPass2(const VkRenderPassCreateInfo2& ci) const;
[[nodiscard]] DescriptorSetLayout CreateDescriptorSetLayout(
const VkDescriptorSetLayoutCreateInfo& ci) const;
@@ -1042,8 +1023,6 @@ public:
[[nodiscard]] Sampler CreateSampler(const VkSamplerCreateInfo& ci) const;
[[nodiscard]] Framebuffer CreateFramebuffer(const VkFramebufferCreateInfo& ci) const;
[[nodiscard]] CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const;
[[nodiscard]] DescriptorUpdateTemplate CreateDescriptorUpdateTemplate(
@@ -1187,15 +1166,6 @@ public:
Check(dld->vkEndCommandBuffer(handle));
}
void BeginRenderPass(const VkRenderPassBeginInfo& renderpass_bi,
VkSubpassContents contents) const noexcept {
dld->vkCmdBeginRenderPass(handle, &renderpass_bi, contents);
}
void EndRenderPass() const noexcept {
dld->vkCmdEndRenderPass(handle);
}
void BeginRendering(const VkRenderingInfo& rendering_info) const noexcept {
dld->vkCmdBeginRendering(handle, &rendering_info);
}