Overlap barriers on window adapt filter + lsfg dedup

This commit is contained in:
CamilleLaVey
2026-09-30 20:58:40 -04:00
parent 51584f5a63
commit e4f74863d2
15 changed files with 233 additions and 248 deletions
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include <algorithm>
#include <span>
#include <string>
#include <vector>
@@ -223,14 +224,15 @@ void FrameGen::Process(const Device& device, VkImageView source, VkExtent2D exte
}
const f32 flow_scale = ConfiguredFlowScale();
const size_t generations = Settings::FrameGenMaxGenerations();
if (!chain || built_extent.width != extent.width || built_extent.height != extent.height ||
built_flow_scale != flow_scale) {
Rebuild(device, extent, flow_scale);
built_flow_scale != flow_scale || built_generations != generations) {
Rebuild(device, extent, flow_scale, generations);
}
const u64 count = frame_count++;
last_count = count;
last_generations = plan.generations;
last_generations = (std::min)(plan.generations, built_generations);
const size_t input_slot = count % INPUT_SLOTS;
const bool warm = plan.warm && count + 1 >= LSFG_REQUIRED_FRAMES &&
@@ -304,7 +306,8 @@ void FrameGen::CreateInputPass(const Device& device) {
input_sampler = CreateNearestNeighborSampler(device);
}
void FrameGen::Rebuild(const Device& device, VkExtent2D extent, f32 flow_scale) {
void FrameGen::Rebuild(const Device& device, VkExtent2D extent, f32 flow_scale,
size_t generations) {
scheduler.Finish();
chain.reset();
@@ -312,10 +315,12 @@ void FrameGen::Rebuild(const Device& device, VkExtent2D extent, f32 flow_scale)
chain.emplace(device, memory_allocator, *shaders, extent, LSFG_DEFAULT_FORMAT,
built_flow_scale);
for (LsfgImage& output : outputs) {
outputs = {};
for (LsfgImage& output : std::span{outputs}.first(generations)) {
output = LsfgImage(device, memory_allocator, extent, LSFG_DEFAULT_FORMAT);
}
built_extent = extent;
built_generations = generations;
frame_count = 0;
warm_streak = 0;
generated = false;
@@ -36,7 +36,7 @@ private:
static constexpr size_t INPUT_SLOTS = 4;
void CreateInputPass(const Device& device);
void Rebuild(const Device& device, VkExtent2D extent, f32 flow_scale);
void Rebuild(const Device& device, VkExtent2D extent, f32 flow_scale, size_t generations);
void DumpDebugImages(u64 count);
MemoryAllocator& memory_allocator;
@@ -58,6 +58,7 @@ private:
FrameGenPlan plan{};
VkExtent2D built_extent{};
f32 built_flow_scale{};
size_t built_generations{};
u64 frame_count{};
u64 last_count{};
size_t last_generations{};
+16 -19
View File
@@ -41,12 +41,9 @@ FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_c
}
void FSR::CreateImages(const Device& device) {
m_dynamic_images.resize(m_image_count);
for (auto& images : m_dynamic_images) {
images.images[Easu] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
images.images[Rcas] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_views[Easu] = CreateWrappedImageView(device, images.images[Easu], VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_views[Rcas] = CreateWrappedImageView(device, images.images[Rcas], VK_FORMAT_R16G16B16A16_SFLOAT);
for (size_t stage = 0; stage < MaxFsrStage; ++stage) {
m_images[stage] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
m_image_views[stage] = CreateWrappedImageView(device, m_images[stage], VK_FORMAT_R16G16B16A16_SFLOAT);
}
}
@@ -79,8 +76,8 @@ void FSR::CreateDescriptorSetLayout(const Device& device) {
void FSR::CreateDescriptorSets(const Device& device) {
std::vector<VkDescriptorSetLayout> layouts(MaxFsrStage, *m_descriptor_set_layout);
for (auto& images : m_dynamic_images)
images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts);
for (size_t i = 0; i < m_image_count; ++i)
m_descriptor_sets.push_back(CreateWrappedDescriptorSets(m_descriptor_pool, layouts));
}
void FSR::CreatePipelineLayouts(const Device& device) {
@@ -112,12 +109,12 @@ void FSR::CreatePipelines(const Device& device) {
}
void FSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) {
Images& images = m_dynamic_images[image_index];
const vk::DescriptorSets& descriptor_sets = m_descriptor_sets[image_index];
std::vector<VkDescriptorImageInfo> image_infos;
image_infos.reserve(2);
std::vector<VkWriteDescriptorSet> updates{
CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[Easu], 0),
CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Easu], images.descriptor_sets[Rcas], 0)
CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, descriptor_sets[Easu], 0),
CreateWriteDescriptorSet(image_infos, *m_sampler, *m_image_views[Easu], descriptor_sets[Rcas], 0)
};
device.GetLogical().UpdateDescriptorSets(updates, {});
}
@@ -125,14 +122,14 @@ void FSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, siz
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) {
Images& images = m_dynamic_images[image_index];
const vk::DescriptorSets& descriptor_sets = m_descriptor_sets[image_index];
VkImage easu_image = *images.images[Easu];
VkImage rcas_image = *images.images[Rcas];
VkDescriptorSet easu_descriptor_set = images.descriptor_sets[Easu];
VkDescriptorSet rcas_descriptor_set = images.descriptor_sets[Rcas];
VkImageView easu_view = *images.image_views[Easu];
VkImageView rcas_view = *images.image_views[Rcas];
VkImage easu_image = *m_images[Easu];
VkImage rcas_image = *m_images[Rcas];
VkDescriptorSet easu_descriptor_set = descriptor_sets[Easu];
VkDescriptorSet rcas_descriptor_set = descriptor_sets[Rcas];
VkImageView easu_view = *m_image_views[Easu];
VkImageView rcas_view = *m_image_views[Rcas];
VkPipeline easu_pipeline = *m_easu_pipeline;
VkPipeline rcas_pipeline = *m_rcas_pipeline;
VkPipelineLayout pipeline_layout = *m_pipeline_layout;
@@ -187,7 +184,7 @@ VkImageView FSR::Draw(const Device& device, Scheduler& scheduler, size_t image_i
TransitionImageLayout(cmdbuf, rcas_image, VK_IMAGE_LAYOUT_GENERAL);
});
return *images.image_views[Rcas];
return rcas_view;
}
} // namespace Vulkan
+3 -6
View File
@@ -54,12 +54,9 @@ private:
vk::Pipeline m_rcas_pipeline;
vk::Sampler m_sampler;
struct Images {
vk::DescriptorSets descriptor_sets;
std::array<vk::Image, MaxFsrStage> images;
std::array<vk::ImageView, MaxFsrStage> image_views;
};
std::vector<Images> m_dynamic_images;
std::array<vk::Image, MaxFsrStage> m_images;
std::array<vk::ImageView, MaxFsrStage> m_image_views;
std::vector<vk::DescriptorSets> m_descriptor_sets;
};
} // namespace Vulkan
+12 -16
View File
@@ -33,11 +33,8 @@ FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
FXAA::~FXAA() = default;
void FXAA::CreateImages(const Device& device, MemoryAllocator& allocator) {
for (u32 i = 0; i < m_image_count; i++) {
Image& image = m_dynamic_images.emplace_back();
image.image = CreateWrappedImage(allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
image.image_view = CreateWrappedImageView(device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT);
}
m_image = CreateWrappedImage(allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
m_image_view = CreateWrappedImageView(device, m_image, VK_FORMAT_R16G16B16A16_SFLOAT);
}
void FXAA::CreateSampler(const Device& device) {
@@ -63,8 +60,8 @@ void FXAA::CreateDescriptorSetLayouts(const Device& device) {
void FXAA::CreateDescriptorSets(const Device& device) {
VkDescriptorSetLayout layout = *m_descriptor_set_layout;
for (auto& images : m_dynamic_images) {
images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, {layout});
for (u32 i = 0; i < m_image_count; i++) {
m_descriptor_sets.push_back(CreateWrappedDescriptorSets(m_descriptor_pool, {layout}));
}
}
@@ -78,23 +75,22 @@ void FXAA::CreatePipelines(const Device& device) {
}
void FXAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) {
Image& image = m_dynamic_images[image_index];
const VkDescriptorSet descriptor_set = m_descriptor_sets[image_index][0];
std::vector<VkDescriptorImageInfo> image_infos;
std::vector<VkWriteDescriptorSet> updates;
image_infos.reserve(2);
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, descriptor_set, 0));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, descriptor_set, 1));
device.GetLogical().UpdateDescriptorSets(updates, {});
}
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 VkImage output_image{*m_image};
const VkImageView output_view{*m_image_view};
const VkDescriptorSet descriptor_set{m_descriptor_sets[image_index][0]};
const VkPipeline pipeline{*m_pipeline};
const VkPipelineLayout layout{*m_pipeline_layout};
const VkExtent2D extent{m_extent};
@@ -114,8 +110,8 @@ void FXAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index,
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
});
*inout_image = *image.image;
*inout_image_view = *image.image_view;
*inout_image = output_image;
*inout_image_view = output_view;
}
} // namespace Vulkan
@@ -34,12 +34,9 @@ private:
void CreatePipelines(const Device& device);
void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index);
struct Image {
vk::DescriptorSets descriptor_sets{};
vk::Image image{};
vk::ImageView image_view{};
};
std::vector<Image> m_dynamic_images{};
vk::Image m_image{};
vk::ImageView m_image_view{};
std::vector<vk::DescriptorSets> m_descriptor_sets{};
const VkExtent2D m_extent;
const u32 m_image_count;
vk::ShaderModule m_vertex_shader{};
@@ -18,6 +18,34 @@ constexpr u32 FIXED_DESCRIPTOR_SETS = 64;
constexpr u32 DESCRIPTOR_SETS_PER_SLOT = 100;
constexpr size_t FIRST_DELTA_LEVEL = 4;
[[nodiscard]] constexpr size_t DeltaStartWave(size_t index) {
if (index == 0) {
return 0;
}
return (FIRST_DELTA_LEVEL + index) * LSFG_GAMMA_STAGES;
}
constexpr size_t GENERATION_WAVES =
DeltaStartWave(LSFG_DELTA_INSTANCES - 1) + LSFG_DELTA_STAGES;
template <typename Func>
void ForEachWaveStage(std::array<LsfgGamma, LSFG_MIP_LEVELS>& gamma,
std::array<LsfgDelta, LSFG_DELTA_INSTANCES>& delta, size_t wave,
Func&& func) {
for (size_t i = 0; i < gamma.size(); ++i) {
const size_t start = i * LSFG_GAMMA_STAGES;
if (wave >= start && wave - start < LSFG_GAMMA_STAGES) {
func(gamma[i], wave - start);
}
}
for (size_t i = 0; i < delta.size(); ++i) {
const size_t start = DeltaStartWave(i);
if (wave >= start && wave - start < LSFG_DELTA_STAGES) {
func(delta[i], wave - start);
}
}
}
} // Anonymous namespace
LsfgChain::LsfgChain(const Device& device, MemoryAllocator& memory_allocator,
@@ -91,11 +119,15 @@ void LsfgChain::DispatchGeneration(vk::CommandBuffer cmdbuf, u64 frame_count,
size_t generation_count, size_t generation, VkImage image,
VkExtent2D extent) {
const size_t slot = LsfgGenerationSlot(generation_count, generation);
for (size_t i = 0; i < LSFG_MIP_LEVELS; ++i) {
gamma[i].Dispatch(cmdbuf, frame_count, slot);
if (i >= FIRST_DELTA_LEVEL) {
delta[i - FIRST_DELTA_LEVEL].Dispatch(cmdbuf, frame_count, slot);
}
for (size_t wave = 0; wave < GENERATION_WAVES; ++wave) {
LsfgBarriers barriers(cmdbuf);
ForEachWaveStage(gamma, delta, wave, [&barriers, frame_count](auto& pass, size_t stage) {
pass.PushBarriers(barriers, frame_count, stage);
});
barriers.Build();
ForEachWaveStage(gamma, delta, wave, [cmdbuf, frame_count, slot](auto& pass, size_t stage) {
pass.DispatchStage(cmdbuf, frame_count, slot, stage);
});
}
generate.Dispatch(cmdbuf, frame_count, slot, image, extent);
}
@@ -196,88 +196,68 @@ LsfgDelta::LsfgDelta(const Device& device, MemoryAllocator& memory_allocator,
}
}
void LsfgDelta::Dispatch(vk::CommandBuffer cmdbuf, u64 frame_count, size_t slot) {
void LsfgDelta::PushBarriers(LsfgBarriers& barriers, u64 frame_count, size_t stage) {
auto& history = (*inputs)[frame_count % LSFG_HISTORY_SLOTS];
auto& previous_history = (*inputs)[(frame_count + 2) % LSFG_HISTORY_SLOTS];
switch (stage) {
case 0:
barriers.WriteToReadAll(previous_history)
.WriteToReadAll(history)
.WriteToRead(previous_gamma)
.ReadToWriteAll(temp1);
break;
case 1:
case 3:
barriers.WriteToReadAll(temp1).ReadToWriteAll(temp2);
break;
case 2:
barriers.WriteToReadAll(temp2).ReadToWriteAll(temp1);
break;
case 4:
barriers.WriteToReadAll(temp2)
.WriteToRead(previous_gamma)
.WriteToRead(*flow_input)
.ReadToWrite(out_image1);
break;
case 5:
barriers.WriteToReadAll(previous_history)
.WriteToReadAll(history)
.WriteToRead(previous_gamma)
.WriteToRead(previous1)
.ReadToWriteAll(temp2);
break;
case 6:
case 8:
barriers.WriteToReadAll(temp2).ReadToWrite(temp1[0]).ReadToWrite(temp1[1]);
break;
case 7:
barriers.WriteToRead(temp1[0]).WriteToRead(temp1[1]).ReadToWriteAll(temp2);
break;
default:
barriers.WriteToRead(temp1[0])
.WriteToRead(temp1[1])
.WriteToRead(previous2)
.ReadToWrite(out_image2);
break;
}
}
void LsfgDelta::DispatchStage(vk::CommandBuffer cmdbuf, u64 frame_count, size_t slot,
size_t stage) const {
const Generation& pass = generations[slot];
const size_t history = frame_count % LSFG_HISTORY_SLOTS;
VkDescriptorSet set = pass.first_descriptor_sets[history];
if (stage == 5) {
set = pass.sixth_descriptor_sets[history];
} else if (stage > 5) {
set = pass.descriptor_sets[stage - 2];
} else if (stage != 0) {
set = pass.descriptor_sets[stage - 1];
}
passes[stage].Bind(cmdbuf, set);
const VkExtent2D extent = temp1[0].Extent();
const u32 groups_x = GroupCount(extent.width);
const u32 groups_y = GroupCount(extent.height);
const size_t history = frame_count % LSFG_HISTORY_SLOTS;
const size_t previous_history = (frame_count + 2) % LSFG_HISTORY_SLOTS;
LsfgBarriers(cmdbuf)
.WriteToReadAll((*inputs)[previous_history])
.WriteToReadAll((*inputs)[history])
.WriteToRead(previous_gamma)
.ReadToWriteAll(temp1)
.Build();
passes[0].Bind(cmdbuf, pass.first_descriptor_sets[history]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf).WriteToReadAll(temp1).ReadToWriteAll(temp2).Build();
passes[1].Bind(cmdbuf, pass.descriptor_sets[0]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf).WriteToReadAll(temp2).ReadToWriteAll(temp1).Build();
passes[2].Bind(cmdbuf, pass.descriptor_sets[1]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf).WriteToReadAll(temp1).ReadToWriteAll(temp2).Build();
passes[3].Bind(cmdbuf, pass.descriptor_sets[2]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToReadAll(temp2)
.WriteToRead(previous_gamma)
.WriteToRead(*flow_input)
.ReadToWrite(out_image1)
.Build();
passes[4].Bind(cmdbuf, pass.descriptor_sets[3]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToReadAll((*inputs)[previous_history])
.WriteToReadAll((*inputs)[history])
.WriteToRead(previous_gamma)
.WriteToRead(previous1)
.ReadToWriteAll(temp2)
.Build();
passes[5].Bind(cmdbuf, pass.sixth_descriptor_sets[history]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToReadAll(temp2)
.ReadToWrite(temp1[0])
.ReadToWrite(temp1[1])
.Build();
passes[6].Bind(cmdbuf, pass.descriptor_sets[4]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToRead(temp1[0])
.WriteToRead(temp1[1])
.ReadToWriteAll(temp2)
.Build();
passes[7].Bind(cmdbuf, pass.descriptor_sets[5]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToReadAll(temp2)
.ReadToWrite(temp1[0])
.ReadToWrite(temp1[1])
.Build();
passes[8].Bind(cmdbuf, pass.descriptor_sets[6]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToRead(temp1[0])
.WriteToRead(temp1[1])
.WriteToRead(previous2)
.ReadToWrite(out_image2)
.Build();
passes[9].Bind(cmdbuf, pass.descriptor_sets[7]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
cmdbuf.Dispatch(GroupCount(extent.width), GroupCount(extent.height), 1);
}
} // namespace Vulkan
@@ -27,7 +27,9 @@ public:
LsfgImageHistory& inputs, LsfgImage& flow_input, LsfgImage* previous_gamma,
LsfgImage* previous1, LsfgImage* previous2);
void Dispatch(vk::CommandBuffer cmdbuf, u64 frame_count, size_t slot);
void PushBarriers(LsfgBarriers& barriers, u64 frame_count, size_t stage);
void DispatchStage(vk::CommandBuffer cmdbuf, u64 frame_count, size_t slot, size_t stage) const;
[[nodiscard]] LsfgImage& Output1() {
return out_image1;
@@ -133,53 +133,43 @@ LsfgGamma::LsfgGamma(const Device& device, MemoryAllocator& memory_allocator,
}
}
void LsfgGamma::Dispatch(vk::CommandBuffer cmdbuf, u64 frame_count, size_t slot) {
void LsfgGamma::PushBarriers(LsfgBarriers& barriers, u64 frame_count, size_t stage) {
switch (stage) {
case 0:
barriers.WriteToReadAll((*inputs)[(frame_count + 2) % LSFG_HISTORY_SLOTS])
.WriteToReadAll((*inputs)[frame_count % LSFG_HISTORY_SLOTS])
.WriteToRead(previous)
.ReadToWriteAll(temp1);
break;
case 1:
barriers.WriteToReadAll(temp1).ReadToWriteAll(temp2);
break;
case 2:
barriers.WriteToReadAll(temp2).ReadToWrite(temp1[0]).ReadToWrite(temp1[1]);
break;
case 3:
barriers.WriteToRead(temp1[0]).WriteToRead(temp1[1]).ReadToWriteAll(temp2);
break;
default:
barriers.WriteToReadAll(temp2)
.WriteToRead(previous)
.WriteToRead(*flow_input)
.ReadToWrite(out_image);
break;
}
}
void LsfgGamma::DispatchStage(vk::CommandBuffer cmdbuf, u64 frame_count, size_t slot,
size_t stage) const {
const Generation& pass = generations[slot];
VkDescriptorSet set = pass.first_descriptor_sets[frame_count % LSFG_HISTORY_SLOTS];
if (stage != 0) {
set = pass.descriptor_sets[stage - 1];
}
passes[stage].Bind(cmdbuf, set);
const VkExtent2D extent = temp1[0].Extent();
const u32 groups_x = GroupCount(extent.width);
const u32 groups_y = GroupCount(extent.height);
const size_t history = frame_count % LSFG_HISTORY_SLOTS;
const size_t previous_history = (frame_count + 2) % LSFG_HISTORY_SLOTS;
LsfgBarriers(cmdbuf)
.WriteToReadAll((*inputs)[previous_history])
.WriteToReadAll((*inputs)[history])
.WriteToRead(previous)
.ReadToWriteAll(temp1)
.Build();
passes[0].Bind(cmdbuf, pass.first_descriptor_sets[history]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf).WriteToReadAll(temp1).ReadToWriteAll(temp2).Build();
passes[1].Bind(cmdbuf, pass.descriptor_sets[0]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToReadAll(temp2)
.ReadToWrite(temp1[0])
.ReadToWrite(temp1[1])
.Build();
passes[2].Bind(cmdbuf, pass.descriptor_sets[1]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToRead(temp1[0])
.WriteToRead(temp1[1])
.ReadToWriteAll(temp2)
.Build();
passes[3].Bind(cmdbuf, pass.descriptor_sets[2]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
LsfgBarriers(cmdbuf)
.WriteToReadAll(temp2)
.WriteToRead(previous)
.WriteToRead(*flow_input)
.ReadToWrite(out_image)
.Build();
passes[4].Bind(cmdbuf, pass.descriptor_sets[3]);
cmdbuf.Dispatch(groups_x, groups_y, 1);
cmdbuf.Dispatch(GroupCount(extent.width), GroupCount(extent.height), 1);
}
} // namespace Vulkan
@@ -26,7 +26,9 @@ public:
LsfgResources& resources, vk::DescriptorPool& descriptor_pool,
LsfgImageHistory& inputs, LsfgImage& flow_input, LsfgImage* previous);
void Dispatch(vk::CommandBuffer cmdbuf, u64 frame_count, size_t slot);
void PushBarriers(LsfgBarriers& barriers, u64 frame_count, size_t stage);
void DispatchStage(vk::CommandBuffer cmdbuf, u64 frame_count, size_t slot, size_t stage) const;
[[nodiscard]] LsfgImage& Output() {
return out_image;
@@ -27,12 +27,8 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image
, m_extent{extent}
, m_edge_dir{edge_dir}
{
// Not finished yet initializing at ctor time?
m_dynamic_images.resize(m_image_count);
for (auto& images : m_dynamic_images) {
images.image = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_view = CreateWrappedImageView(device, images.image, VK_FORMAT_R16G16B16A16_SFLOAT);
}
m_image = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
m_image_view = CreateWrappedImageView(device, m_image, VK_FORMAT_R16G16B16A16_SFLOAT);
m_sampler = CreateBilinearSampler(device);
m_vert_shader = BuildShader(device, SGSR1_SHADER_VERT_SPV);
@@ -44,8 +40,8 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image
m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
VkDescriptorSetLayout layout = *m_descriptor_set_layout;
for (auto& images : m_dynamic_images)
images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layout);
for (size_t i = 0; i < m_image_count; ++i)
m_descriptor_sets.push_back(CreateWrappedDescriptorSets(m_descriptor_pool, layout));
const VkPushConstantRange range{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
@@ -68,19 +64,17 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image
}
void SGSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) {
Images& images = m_dynamic_images[image_index];
std::vector<VkDescriptorImageInfo> image_infos;
std::vector<VkWriteDescriptorSet> updates;
image_infos.reserve(1);
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[0], 0));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, m_descriptor_sets[image_index][0], 0));
device.GetLogical().UpdateDescriptorSets(updates, {});
}
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 output_image = *m_image;
auto const output_view = *m_image_view;
auto const descriptor_set = m_descriptor_sets[image_index][0];
auto const pipeline = *m_stage_pipeline;
VkPipelineLayout layout = *m_pipeline_layout;
@@ -126,7 +120,7 @@ VkImageView SGSR::Draw(const Device& device, Scheduler& scheduler, size_t image_
cmdbuf.EndRendering();
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
});
return *images.image_view;
return output_view;
}
} // namespace Vulkan
@@ -33,12 +33,9 @@ private:
vk::Pipeline m_stage_pipeline;
vk::Sampler m_sampler;
struct Images {
vk::DescriptorSets descriptor_sets;
vk::Image image;
vk::ImageView image_view;
};
std::vector<Images> m_dynamic_images;
vk::Image m_image;
vk::ImageView m_image_view;
std::vector<vk::DescriptorSets> m_descriptor_sets;
bool m_edge_dir{};
};
+36 -38
View File
@@ -55,22 +55,18 @@ void SMAA::CreateImages(const Device& device) {
m_static_image_views[Search] =
CreateWrappedImageView(device, m_static_images[Search], VK_FORMAT_R8_UNORM);
for (u32 i = 0; i < m_image_count; i++) {
Images& images = m_dynamic_images.emplace_back();
m_dynamic_images[Blend] =
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
m_dynamic_images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT);
m_dynamic_images[Output] =
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
images.images[Blend] =
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
images.images[Edges] = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16_SFLOAT);
images.images[Output] =
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_views[Blend] =
CreateWrappedImageView(device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_views[Edges] =
CreateWrappedImageView(device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT);
images.image_views[Output] =
CreateWrappedImageView(device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT);
}
m_dynamic_image_views[Blend] =
CreateWrappedImageView(device, m_dynamic_images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT);
m_dynamic_image_views[Edges] =
CreateWrappedImageView(device, m_dynamic_images[Edges], VK_FORMAT_R16G16_SFLOAT);
m_dynamic_image_views[Output] =
CreateWrappedImageView(device, m_dynamic_images[Output], VK_FORMAT_R16G16B16A16_SFLOAT);
}
void SMAA::CreateSampler(const Device& device) {
@@ -122,8 +118,8 @@ void SMAA::CreateDescriptorSets(const Device& device) {
std::ranges::transform(m_descriptor_set_layouts, layouts.begin(),
[](auto& layout) { return *layout; });
for (auto& images : m_dynamic_images) {
images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts);
for (u32 i = 0; i < m_image_count; i++) {
m_descriptor_sets.push_back(CreateWrappedDescriptorSets(m_descriptor_pool, layouts));
}
}
@@ -147,28 +143,30 @@ void SMAA::CreatePipelines(const Device& device) {
}
void SMAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) {
Images& images = m_dynamic_images[image_index];
const vk::DescriptorSets& descriptor_sets = m_descriptor_sets[image_index];
std::vector<VkDescriptorImageInfo> image_infos;
std::vector<VkWriteDescriptorSet> updates;
image_infos.reserve(6);
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
images.descriptor_sets[EdgeDetection], 0));
descriptor_sets[EdgeDetection], 0));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Edges],
images.descriptor_sets[BlendingWeightCalculation],
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler,
*m_dynamic_image_views[Edges],
descriptor_sets[BlendingWeightCalculation],
0));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Area],
images.descriptor_sets[BlendingWeightCalculation],
descriptor_sets[BlendingWeightCalculation],
1));
updates.push_back(
CreateWriteDescriptorSet(image_infos, *m_sampler, *m_static_image_views[Search],
images.descriptor_sets[BlendingWeightCalculation], 2));
descriptor_sets[BlendingWeightCalculation], 2));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view,
images.descriptor_sets[NeighborhoodBlending], 0));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend],
images.descriptor_sets[NeighborhoodBlending], 1));
descriptor_sets[NeighborhoodBlending], 0));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler,
*m_dynamic_image_views[Blend],
descriptor_sets[NeighborhoodBlending], 1));
device.GetLogical().UpdateDescriptorSets(updates, {});
}
@@ -190,22 +188,22 @@ void SMAA::UploadImages(const Device& device, Scheduler& scheduler) {
}
void SMAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) {
Images& images = m_dynamic_images[image_index];
const vk::DescriptorSets& descriptor_sets = m_descriptor_sets[image_index];
VkImage input_image = *inout_image;
VkImage output_image = *images.images[Output];
VkImage edges_image = *images.images[Edges];
VkImage blend_image = *images.images[Blend];
VkImage output_image = *m_dynamic_images[Output];
VkImage edges_image = *m_dynamic_images[Edges];
VkImage blend_image = *m_dynamic_images[Blend];
VkDescriptorSet edge_detection_descriptor_set = images.descriptor_sets[EdgeDetection];
VkDescriptorSet edge_detection_descriptor_set = descriptor_sets[EdgeDetection];
VkDescriptorSet blending_weight_calculation_descriptor_set =
images.descriptor_sets[BlendingWeightCalculation];
descriptor_sets[BlendingWeightCalculation];
VkDescriptorSet neighborhood_blending_descriptor_set =
images.descriptor_sets[NeighborhoodBlending];
descriptor_sets[NeighborhoodBlending];
VkImageView edges_view = *images.image_views[Edges];
VkImageView blend_view = *images.image_views[Blend];
VkImageView output_view = *images.image_views[Output];
VkImageView edges_view = *m_dynamic_image_views[Edges];
VkImageView blend_view = *m_dynamic_image_views[Blend];
VkImageView output_view = *m_dynamic_image_views[Output];
UploadImages(device, scheduler);
UpdateDescriptorSets(device, *inout_image_view, image_index);
@@ -248,8 +246,8 @@ void SMAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index,
TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL);
});
*inout_image = *images.images[Output];
*inout_image_view = *images.image_views[Output];
*inout_image = *m_dynamic_images[Output];
*inout_image_view = *m_dynamic_image_views[Output];
}
} // namespace Vulkan
@@ -71,12 +71,9 @@ private:
std::array<vk::Image, MaxStaticImage> m_static_images{};
std::array<vk::ImageView, MaxStaticImage> m_static_image_views{};
struct Images {
vk::DescriptorSets descriptor_sets{};
std::array<vk::Image, MaxDynamicImage> images{};
std::array<vk::ImageView, MaxDynamicImage> image_views{};
};
std::vector<Images> m_dynamic_images{};
std::array<vk::Image, MaxDynamicImage> m_dynamic_images{};
std::array<vk::ImageView, MaxDynamicImage> m_dynamic_image_views{};
std::vector<vk::DescriptorSets> m_descriptor_sets{};
bool m_images_ready{};
vk::Sampler m_sampler{};