mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-06 22:10:49 +00:00
Overlap barriers on window adapt filter + lsfg dedup
This commit is contained in:
@@ -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{};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{};
|
||||
};
|
||||
|
||||
|
||||
@@ -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{};
|
||||
|
||||
Reference in New Issue
Block a user