[video_core, hle] remove redundant parent references in system structs (#3908)

reworked a bit to remove references of parent objects and instead pass as arguments to methods to prevent useless reloads

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Co-authored-by: maufeat <sahyno1996@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3908
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
lizzie 2026-06-23 06:31:25 +02:00 committed by crueter
parent f8facda35f
commit 3aa0d46259
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
307 changed files with 4419 additions and 4477 deletions

View file

@ -502,9 +502,9 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
two_textures_set_layout(device.GetLogical().CreateDescriptorSetLayout(
TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)),
one_texture_descriptor_allocator{
descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)},
descriptor_pool.Allocator(device_, scheduler_, *one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)},
two_textures_descriptor_allocator{
descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)},
descriptor_pool.Allocator(device_, scheduler_, *two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)},
one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
one_texture_set_layout.address(),
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>))),

View file

@ -31,14 +31,13 @@ static u64 GetUint64(const VkPipelineExecutableStatisticKHR& statistic) {
}
}
PipelineStatistics::PipelineStatistics(const Device& device_) : device{device_} {}
PipelineStatistics::PipelineStatistics(const Device& device_) {}
void PipelineStatistics::Collect(VkPipeline pipeline) {
const auto& dev{device.GetLogical()};
const std::vector properties{dev.GetPipelineExecutablePropertiesKHR(pipeline)};
void PipelineStatistics::Collect(const Device& device, VkPipeline pipeline) {
const std::vector properties{device.GetLogical().GetPipelineExecutablePropertiesKHR(pipeline)};
const u32 num_executables{static_cast<u32>(properties.size())};
for (u32 executable = 0; executable < num_executables; ++executable) {
const auto statistics{dev.GetPipelineExecutableStatisticsKHR(pipeline, executable)};
const auto statistics{device.GetLogical().GetPipelineExecutableStatisticsKHR(pipeline, executable)};
if (statistics.empty()) {
continue;
}

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -16,9 +19,7 @@ class Device;
class PipelineStatistics {
public:
explicit PipelineStatistics(const Device& device_);
void Collect(VkPipeline pipeline);
void Collect(const Device& device, VkPipeline pipeline);
void Report() const;
private:
@ -30,8 +31,6 @@ private:
u64 branches_count{};
u64 basic_block_count{};
};
const Device& device;
mutable std::mutex mutex;
std::vector<Stats> collected_stats;
};

View file

@ -11,12 +11,12 @@
namespace Vulkan {
class Scheduler;
class Device;
class AntiAliasPass {
public:
virtual ~AntiAliasPass() = default;
virtual void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image,
VkImageView* inout_image_view) = 0;
virtual void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) = 0;
};
} // namespace Vulkan

View file

@ -25,74 +25,74 @@ using namespace FSR;
using PushConstants = std::array<u32, 4 * 4>;
FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count,
VkExtent2D extent)
: m_device{device}, m_memory_allocator{memory_allocator},
m_image_count{image_count}, m_extent{extent} {
CreateImages();
CreateRenderPasses();
CreateSampler();
CreateShaders();
CreateDescriptorPool();
CreateDescriptorSetLayout();
CreateDescriptorSets();
CreatePipelineLayouts();
CreatePipelines();
FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent)
: m_memory_allocator{memory_allocator}
, m_image_count{image_count}
, m_extent{extent}
{
CreateImages(device);
CreateRenderPasses(device);
CreateSampler(device);
CreateShaders(device);
CreateDescriptorPool(device);
CreateDescriptorSetLayout(device);
CreateDescriptorSets(device);
CreatePipelineLayouts(device);
CreatePipelines(device);
}
void FSR::CreateImages() {
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(m_device, images.images[Easu], VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_views[Rcas] = CreateWrappedImageView(m_device, images.images[Rcas], 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);
}
}
void FSR::CreateRenderPasses() {
m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
void FSR::CreateRenderPasses(const Device& device) {
m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
for (auto& images : m_dynamic_images) {
images.framebuffers[Easu] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Easu], m_extent);
images.framebuffers[Rcas] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Rcas], m_extent);
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() {
m_sampler = CreateBilinearSampler(m_device);
void FSR::CreateSampler(const Device& device) {
m_sampler = CreateBilinearSampler(device);
}
void FSR::CreateShaders() {
m_vert_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_VERT_SPV);
void FSR::CreateShaders(const Device& device) {
m_vert_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_VERT_SPV);
if (m_device.IsFloat16Supported()) {
m_easu_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_EASU_FP16_FRAG_SPV);
m_rcas_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_FRAG_SPV);
if (device.IsFloat16Supported()) {
m_easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP16_FRAG_SPV);
m_rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_FRAG_SPV);
} else {
m_easu_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_EASU_FP32_FRAG_SPV);
m_rcas_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_FRAG_SPV);
m_easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP32_FRAG_SPV);
m_rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_FRAG_SPV);
}
}
void FSR::CreateDescriptorPool() {
void FSR::CreateDescriptorPool(const Device& device) {
// EASU: 1 descriptor
// RCAS: 1 descriptor
// 2 descriptors, 2 descriptor sets per invocation
m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, 2 * m_image_count);
m_descriptor_pool = CreateWrappedDescriptorPool(device, 2 * m_image_count, 2 * m_image_count);
}
void FSR::CreateDescriptorSetLayout() {
m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
void FSR::CreateDescriptorSetLayout(const Device& device) {
m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
}
void FSR::CreateDescriptorSets() {
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);
}
void FSR::CreatePipelineLayouts() {
void FSR::CreatePipelineLayouts(const Device& device) {
const VkPushConstantRange range{
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = 0,
@ -108,17 +108,17 @@ void FSR::CreatePipelineLayouts() {
.pPushConstantRanges = &range,
};
m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci);
m_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci);
}
void FSR::CreatePipelines() {
m_easu_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout,
void FSR::CreatePipelines(const Device& device) {
m_easu_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout,
std::tie(m_vert_shader, m_easu_shader));
m_rcas_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout,
m_rcas_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout,
std::tie(m_vert_shader, m_rcas_shader));
}
void FSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
void FSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) {
Images& images = m_dynamic_images[image_index];
std::vector<VkDescriptorImageInfo> image_infos;
image_infos.reserve(2);
@ -126,10 +126,10 @@ void FSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
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)
};
m_device.GetLogical().UpdateDescriptorSets(updates, {});
device.GetLogical().UpdateDescriptorSets(updates, {});
}
void FSR::UploadImages(Scheduler& scheduler) {
void FSR::UploadImages(const Device& device, Scheduler& scheduler) {
if (!m_images_ready) {
m_images_ready = true;
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
@ -142,7 +142,7 @@ void FSR::UploadImages(Scheduler& scheduler) {
}
}
VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
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];
@ -179,8 +179,8 @@ VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_i
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
FsrRcasCon(rcas_con.data(), sharpening);
UploadImages(scheduler);
UpdateDescriptorSets(source_image_view, image_index);
UploadImages(device, scheduler);
UpdateDescriptorSets(device, source_image_view, image_index);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([=](vk::CommandBuffer cmdbuf) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -14,27 +17,25 @@ class Scheduler;
class FSR {
public:
explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count,
VkExtent2D extent);
VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image,
explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent);
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 CreateImages();
void CreateRenderPasses();
void CreateSampler();
void CreateShaders();
void CreateDescriptorPool();
void CreateDescriptorSetLayout();
void CreateDescriptorSets();
void CreatePipelineLayouts();
void CreatePipelines();
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);
void CreateDescriptorSetLayout(const Device& device);
void CreateDescriptorSets(const Device& device);
void CreatePipelineLayouts(const Device& device);
void CreatePipelines(const Device& device);
void UploadImages(Scheduler& scheduler);
void UpdateDescriptorSets(VkImageView image_view, size_t image_index);
void UploadImages(const Device& device, Scheduler& scheduler);
void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index);
const Device& m_device;
MemoryAllocator& m_memory_allocator;
const size_t m_image_count;
const VkExtent2D m_extent;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -14,61 +17,60 @@
namespace Vulkan {
FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
: m_device(device), m_allocator(allocator), m_extent(extent),
m_image_count(static_cast<u32>(image_count)) {
CreateImages();
CreateRenderPasses();
CreateSampler();
CreateShaders();
CreateDescriptorPool();
CreateDescriptorSetLayouts();
CreateDescriptorSets();
CreatePipelineLayouts();
CreatePipelines();
: m_extent(extent)
, m_image_count(u32(image_count))
{
CreateImages(device, allocator);
CreateRenderPasses(device);
CreateSampler(device);
CreateShaders(device);
CreateDescriptorPool(device);
CreateDescriptorSetLayouts(device);
CreateDescriptorSets(device);
CreatePipelineLayouts(device);
CreatePipelines(device);
}
FXAA::~FXAA() = default;
void FXAA::CreateImages() {
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(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
image.image_view =
CreateWrappedImageView(m_device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT);
image.image = CreateWrappedImage(allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
image.image_view = CreateWrappedImageView(device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT);
}
}
void FXAA::CreateRenderPasses() {
m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
void FXAA::CreateRenderPasses(const Device& device) {
m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
for (auto& image : m_dynamic_images) {
image.framebuffer =
CreateWrappedFramebuffer(m_device, m_renderpass, image.image_view, m_extent);
CreateWrappedFramebuffer(device, m_renderpass, image.image_view, m_extent);
}
}
void FXAA::CreateSampler() {
m_sampler = CreateWrappedSampler(m_device);
void FXAA::CreateSampler(const Device& device) {
m_sampler = CreateWrappedSampler(device);
}
void FXAA::CreateShaders() {
m_vertex_shader = CreateWrappedShaderModule(m_device, FXAA_VERT_SPV);
m_fragment_shader = CreateWrappedShaderModule(m_device, FXAA_FRAG_SPV);
void FXAA::CreateShaders(const Device& device) {
m_vertex_shader = CreateWrappedShaderModule(device, FXAA_VERT_SPV);
m_fragment_shader = CreateWrappedShaderModule(device, FXAA_FRAG_SPV);
}
void FXAA::CreateDescriptorPool() {
void FXAA::CreateDescriptorPool(const Device& device) {
// 2 descriptors, 1 descriptor set per image
m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, m_image_count);
m_descriptor_pool = CreateWrappedDescriptorPool(device, 2 * m_image_count, m_image_count);
}
void FXAA::CreateDescriptorSetLayouts() {
void FXAA::CreateDescriptorSetLayouts(const Device& device) {
m_descriptor_set_layout =
CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
}
void FXAA::CreateDescriptorSets() {
void FXAA::CreateDescriptorSets(const Device& device) {
VkDescriptorSetLayout layout = *m_descriptor_set_layout;
for (auto& images : m_dynamic_images) {
@ -76,30 +78,28 @@ void FXAA::CreateDescriptorSets() {
}
}
void FXAA::CreatePipelineLayouts() {
m_pipeline_layout = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layout);
void FXAA::CreatePipelineLayouts(const Device& device) {
m_pipeline_layout = CreateWrappedPipelineLayout(device, m_descriptor_set_layout);
}
void FXAA::CreatePipelines() {
m_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout,
void FXAA::CreatePipelines(const Device& device) {
m_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout,
std::tie(m_vertex_shader, m_fragment_shader));
}
void FXAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
void FXAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) {
Image& image = m_dynamic_images[image_index];
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, image.descriptor_sets[0], 0));
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1));
m_device.GetLogical().UpdateDescriptorSets(updates, {});
device.GetLogical().UpdateDescriptorSets(updates, {});
}
void FXAA::UploadImages(Scheduler& scheduler) {
void FXAA::UploadImages(const Device& device, Scheduler& scheduler) {
if (m_images_ready) {
return;
}
@ -114,8 +114,7 @@ void FXAA::UploadImages(Scheduler& scheduler) {
m_images_ready = true;
}
void FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image,
VkImageView* inout_image_view) {
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};
@ -126,8 +125,8 @@ void FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image,
const VkPipelineLayout layout{*m_pipeline_layout};
const VkExtent2D extent{m_extent};
UploadImages(scheduler);
UpdateDescriptorSets(*inout_image_view, image_index);
UploadImages(device, scheduler);
UpdateDescriptorSets(device, *inout_image_view, image_index);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([=](vk::CommandBuffer cmdbuf) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -15,38 +18,23 @@ class StagingBufferPool;
class FXAA final : public AntiAliasPass {
public:
explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
VkExtent2D extent);
explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent);
~FXAA() override;
void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image,
VkImageView* inout_image_view) override;
void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) override;
private:
void CreateImages();
void CreateRenderPasses();
void CreateSampler();
void CreateShaders();
void CreateDescriptorPool();
void CreateDescriptorSetLayouts();
void CreateDescriptorSets();
void CreatePipelineLayouts();
void CreatePipelines();
void UpdateDescriptorSets(VkImageView image_view, size_t image_index);
void UploadImages(Scheduler& scheduler);
const Device& m_device;
MemoryAllocator& m_allocator;
const VkExtent2D m_extent;
const u32 m_image_count;
vk::ShaderModule m_vertex_shader{};
vk::ShaderModule m_fragment_shader{};
vk::DescriptorPool m_descriptor_pool{};
vk::DescriptorSetLayout m_descriptor_set_layout{};
vk::PipelineLayout m_pipeline_layout{};
vk::Pipeline m_pipeline{};
vk::RenderPass m_renderpass{};
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);
void CreateDescriptorSetLayouts(const Device& device);
void CreateDescriptorSets(const Device& device);
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{};
@ -55,9 +43,17 @@ private:
vk::ImageView image_view{};
};
std::vector<Image> m_dynamic_images{};
bool m_images_ready{};
const VkExtent2D m_extent;
const u32 m_image_count;
vk::ShaderModule m_vertex_shader{};
vk::ShaderModule m_fragment_shader{};
vk::DescriptorPool m_descriptor_pool{};
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

View file

@ -56,13 +56,15 @@ VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
} // Anonymous namespace
Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
Tegra::MaxwellDeviceMemoryManager& device_memory_, size_t image_count_,
VkExtent2D output_size, VkDescriptorSetLayout layout, const PresentFilters& filters_)
: device(device_), memory_allocator(memory_allocator_), scheduler(scheduler_),
device_memory(device_memory_), filters(filters_), image_count(image_count_) {
CreateDescriptorPool();
CreateDescriptorSets(layout);
Layer::Layer(const Device& device, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, Tegra::MaxwellDeviceMemoryManager& device_memory_, size_t image_count_, VkExtent2D output_size, VkDescriptorSetLayout layout, const PresentFilters& filters_)
: memory_allocator(memory_allocator_)
, scheduler(scheduler_)
, device_memory(device_memory_)
, filters(filters_)
, image_count(image_count_)
{
CreateDescriptorPool(device);
CreateDescriptorSets(device, layout);
if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) {
sr_filter.emplace<FSR>(device, memory_allocator, image_count, output_size);
} else if (filters.get_scaling_filter() == Settings::ScalingFilter::Sgsr) {
@ -76,7 +78,7 @@ Layer::~Layer() {
ReleaseRawImages();
}
void Layer::ConfigureDraw(PresentPushConstants* out_push_constants,
void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_constants,
VkDescriptorSet* out_descriptor_set, RasterizerVulkan& rasterizer,
VkSampler sampler, size_t image_index,
const Tegra::FramebufferConfig& framebuffer,
@ -89,8 +91,8 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants,
const u32 scaled_height = texture_info ? texture_info->scaled_height : texture_height;
const bool use_accelerated = texture_info.has_value();
RefreshResources(framebuffer);
SetAntiAliasPass();
RefreshResources(device, framebuffer);
SetAntiAliasPass(device);
// Finish any pending renderpass
scheduler.RequestOutsideRenderPassOperationContext();
@ -108,9 +110,9 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants,
texture_info ? texture_info->image_view : *raw_image_views[image_index];
if (auto* fxaa = std::get_if<FXAA>(&anti_alias)) {
fxaa->Draw(scheduler, image_index, &source_image, &source_image_view);
fxaa->Draw(device, scheduler, image_index, &source_image, &source_image_view);
} else if (auto* smaa = std::get_if<SMAA>(&anti_alias)) {
smaa->Draw(scheduler, image_index, &source_image, &source_image_view);
smaa->Draw(device, scheduler, image_index, &source_image, &source_image_view);
}
auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height);
@ -120,30 +122,30 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants,
};
if (auto* fsr = std::get_if<FSR>(&sr_filter)) {
source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect);
source_image_view = fsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect);
crop_rect = {0, 0, 1, 1};
} else if (auto* sgsr = std::get_if<SGSR>(&sr_filter)) {
source_image_view = sgsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect);
source_image_view = sgsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect);
crop_rect = {0, 0, 1, 1};
}
SetMatrixData(*out_push_constants, layout);
SetVertexData(*out_push_constants, layout, crop_rect);
SetMatrixData(device, *out_push_constants, layout);
SetVertexData(device, *out_push_constants, layout, crop_rect);
UpdateDescriptorSet(source_image_view, sampler, image_index);
UpdateDescriptorSet(device, source_image_view, sampler, image_index);
*out_descriptor_set = descriptor_sets[image_index];
}
void Layer::CreateDescriptorPool() {
void Layer::CreateDescriptorPool(const Device& device) {
descriptor_pool = CreateWrappedDescriptorPool(device, image_count, image_count);
}
void Layer::CreateDescriptorSets(VkDescriptorSetLayout layout) {
void Layer::CreateDescriptorSets(const Device& device, VkDescriptorSetLayout layout) {
const std::vector layouts(image_count, layout);
descriptor_sets = CreateWrappedDescriptorSets(descriptor_pool, layouts);
}
void Layer::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
void Layer::CreateStagingBuffer(const Device& device, const Tegra::FramebufferConfig& framebuffer) {
const VkBufferCreateInfo ci{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
@ -159,7 +161,7 @@ void Layer::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload);
}
void Layer::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
void Layer::CreateRawImages(const Device& device, const Tegra::FramebufferConfig& framebuffer) {
const auto format = GetFormat(framebuffer);
resource_ticks.resize(image_count);
raw_images.resize(image_count);
@ -172,7 +174,7 @@ void Layer::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
}
}
void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) {
void Layer::RefreshResources(const Device& device, const Tegra::FramebufferConfig& framebuffer) {
if (framebuffer.width == raw_width && framebuffer.height == raw_height &&
framebuffer.pixel_format == pixel_format && !raw_images.empty()) {
return;
@ -184,11 +186,11 @@ void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) {
anti_alias.emplace<std::monostate>();
ReleaseRawImages();
CreateStagingBuffer(framebuffer);
CreateRawImages(framebuffer);
CreateStagingBuffer(device, framebuffer);
CreateRawImages(device, framebuffer);
}
void Layer::SetAntiAliasPass() {
void Layer::SetAntiAliasPass(const Device& device) {
if (!std::holds_alternative<std::monostate>(anti_alias) && anti_alias_setting == filters.get_anti_aliasing())
return;
@ -229,20 +231,17 @@ u64 Layer::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer,
return GetSizeInBytes(framebuffer) * image_index;
}
void Layer::SetMatrixData(PresentPushConstants& data,
const Layout::FramebufferLayout& layout) const {
data.modelview_matrix =
MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height));
void Layer::SetMatrixData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout) const {
data.modelview_matrix = MakeOrthographicMatrix(f32(layout.width), static_cast<f32>(layout.height));
}
void Layer::SetVertexData(PresentPushConstants& data, const Layout::FramebufferLayout& layout,
const Common::Rectangle<f32>& crop) const {
void Layer::SetVertexData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout, const Common::Rectangle<f32>& crop) const {
// Map the coordinates to the screen.
const auto& screen = layout.screen;
const auto x = static_cast<f32>(screen.left);
const auto y = static_cast<f32>(screen.top);
const auto w = static_cast<f32>(screen.GetWidth());
const auto h = static_cast<f32>(screen.GetHeight());
const auto x = f32(screen.left);
const auto y = f32(screen.top);
const auto w = f32(screen.GetWidth());
const auto h = f32(screen.GetHeight());
data.vertices[0] = ScreenRectVertex(x, y, crop.left, crop.top);
data.vertices[1] = ScreenRectVertex(x + w, y, crop.right, crop.top);
@ -250,7 +249,7 @@ void Layer::SetVertexData(PresentPushConstants& data, const Layout::FramebufferL
data.vertices[3] = ScreenRectVertex(x + w, y + h, crop.right, crop.bottom);
}
void Layer::UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_t image_index) {
void Layer::UpdateDescriptorSet(const Device& device, VkImageView image_view, VkSampler sampler, size_t image_index) {
const VkDescriptorImageInfo image_info{
.sampler = sampler,
.imageView = image_view,

View file

@ -52,33 +52,31 @@ public:
const PresentFilters& filters);
~Layer();
void ConfigureDraw(PresentPushConstants* out_push_constants,
void ConfigureDraw(const Device& device, PresentPushConstants* out_push_constants,
VkDescriptorSet* out_descriptor_set, RasterizerVulkan& rasterizer,
VkSampler sampler, size_t image_index,
const Tegra::FramebufferConfig& framebuffer,
const Layout::FramebufferLayout& layout);
private:
void CreateDescriptorPool();
void CreateDescriptorSets(VkDescriptorSetLayout layout);
void CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer);
void CreateRawImages(const Tegra::FramebufferConfig& framebuffer);
void CreateDescriptorPool(const Device& device);
void CreateDescriptorSets(const Device& device, VkDescriptorSetLayout layout);
void CreateStagingBuffer(const Device& device, const Tegra::FramebufferConfig& framebuffer);
void CreateRawImages(const Device& device, const Tegra::FramebufferConfig& framebuffer);
void RefreshResources(const Tegra::FramebufferConfig& framebuffer);
void SetAntiAliasPass();
void RefreshResources(const Device& device, const Tegra::FramebufferConfig& framebuffer);
void SetAntiAliasPass(const Device& device);
void ReleaseRawImages();
u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const;
u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, size_t image_index) const;
void SetMatrixData(PresentPushConstants& data, const Layout::FramebufferLayout& layout) const;
void SetVertexData(PresentPushConstants& data, const Layout::FramebufferLayout& layout,
const Common::Rectangle<f32>& crop) const;
void UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_t image_index);
void SetMatrixData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout) const;
void SetVertexData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout, const Common::Rectangle<f32>& crop) const;
void UpdateDescriptorSet(const Device& device, VkImageView image_view, VkSampler sampler, size_t image_index);
void UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t image_index);
private:
const Device& device;
MemoryAllocator& memory_allocator;
Scheduler& scheduler;
Tegra::MaxwellDeviceMemoryManager& device_memory;

View file

@ -20,8 +20,7 @@ namespace Vulkan {
using PushConstants = std::array<u32, 4 + 2 + 1>;
SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir)
: m_device{device}
, m_memory_allocator{memory_allocator}
: m_memory_allocator{memory_allocator}
, m_image_count{image_count}
, m_extent{extent}
, m_edge_dir{edge_dir}
@ -30,21 +29,21 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image
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(m_device, images.image, VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_view = CreateWrappedImageView(device, images.image, VK_FORMAT_R16G16B16A16_SFLOAT);
}
m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
for (auto& images : m_dynamic_images)
images.framebuffer = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_view, m_extent);
images.framebuffer = CreateWrappedFramebuffer(device, m_renderpass, images.image_view, m_extent);
m_sampler = CreateBilinearSampler(m_device);
m_vert_shader = BuildShader(m_device, SGSR1_SHADER_VERT_SPV);
m_sampler = CreateBilinearSampler(device);
m_vert_shader = BuildShader(device, SGSR1_SHADER_VERT_SPV);
m_stage_shader = m_edge_dir
? BuildShader(m_device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV)
: BuildShader(m_device, SGSR1_SHADER_MOBILE_FRAG_SPV);
? BuildShader(device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV)
: BuildShader(device, SGSR1_SHADER_MOBILE_FRAG_SPV);
// 2 descriptors, 2 descriptor sets per invocation
m_descriptor_pool = CreateWrappedDescriptorPool(m_device, m_image_count, m_image_count);
m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
m_descriptor_pool = CreateWrappedDescriptorPool(device, m_image_count, m_image_count);
m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
VkDescriptorSetLayout layout = *m_descriptor_set_layout;
for (auto& images : m_dynamic_images)
@ -64,20 +63,20 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image
.pushConstantRangeCount = 1,
.pPushConstantRanges = &range,
};
m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci);
m_stage_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader));
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));
}
void SGSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
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));
m_device.GetLogical().UpdateDescriptorSets(updates, {});
device.GetLogical().UpdateDescriptorSets(updates, {});
}
void SGSR::UploadImages(Scheduler& scheduler) {
void SGSR::UploadImages(const Device& device, Scheduler& scheduler) {
if (!m_images_ready) {
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
for (auto& image : m_dynamic_images)
@ -88,7 +87,7 @@ void SGSR::UploadImages(Scheduler& scheduler) {
}
}
VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle<f32>& crop_rect) {
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 descriptor_set = images.descriptor_sets[0];
@ -122,8 +121,8 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_
viewport_con[5] = std::bit_cast<u32>(viewport_height / input_image_height);
viewport_con[6] = std::bit_cast<u32>(sharpening);
UploadImages(scheduler);
UpdateDescriptorSets(source_image_view, image_index);
UploadImages(device, scheduler);
UpdateDescriptorSets(device, source_image_view, image_index);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([=](vk::CommandBuffer cmdbuf) {

View file

@ -16,13 +16,12 @@ class SGSR {
public:
static constexpr size_t SGSR_STAGE_COUNT = 1;
explicit SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir);
VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle<f32>& crop_rect);
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();
void UploadImages(Scheduler& scheduler);
void UpdateDescriptorSets(VkImageView image_view, size_t image_index);
void Initialize(const Device& device);
void UploadImages(const Device& device, Scheduler& scheduler);
void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index);
const Device& m_device;
MemoryAllocator& m_memory_allocator;
const size_t m_image_count;
const VkExtent2D m_extent;

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@ -27,22 +27,24 @@
namespace Vulkan {
SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent)
: m_device(device), m_allocator(allocator), m_extent(extent),
m_image_count(static_cast<u32>(image_count)) {
CreateImages();
CreateRenderPasses();
CreateSampler();
CreateShaders();
CreateDescriptorPool();
CreateDescriptorSetLayouts();
CreateDescriptorSets();
CreatePipelineLayouts();
CreatePipelines();
: m_allocator(allocator)
, m_extent(extent)
, m_image_count(u32(image_count))
{
CreateImages(device);
CreateRenderPasses(device);
CreateSampler(device);
CreateShaders(device);
CreateDescriptorPool(device);
CreateDescriptorSetLayouts(device);
CreateDescriptorSets(device);
CreatePipelineLayouts(device);
CreatePipelines(device);
}
SMAA::~SMAA() = default;
void SMAA::CreateImages() {
void SMAA::CreateImages(const Device& device) {
static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
@ -50,9 +52,9 @@ void SMAA::CreateImages() {
m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM);
m_static_image_views[Area] =
CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM);
CreateWrappedImageView(device, m_static_images[Area], VK_FORMAT_R8G8_UNORM);
m_static_image_views[Search] =
CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM);
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();
@ -64,39 +66,39 @@ void SMAA::CreateImages() {
CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_views[Blend] =
CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT);
CreateWrappedImageView(device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT);
images.image_views[Edges] =
CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT);
CreateWrappedImageView(device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT);
images.image_views[Output] =
CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT);
CreateWrappedImageView(device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT);
}
}
void SMAA::CreateRenderPasses() {
m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT);
void SMAA::CreateRenderPasses(const Device& device) {
m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(device, VK_FORMAT_R16G16_SFLOAT);
m_renderpasses[BlendingWeightCalculation] =
CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
m_renderpasses[NeighborhoodBlending] =
CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT);
CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT);
for (auto& images : m_dynamic_images) {
images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer(
m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent);
device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent);
images.framebuffers[BlendingWeightCalculation] =
CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation],
CreateWrappedFramebuffer(device, m_renderpasses[BlendingWeightCalculation],
images.image_views[Blend], m_extent);
images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer(
m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent);
device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent);
}
}
void SMAA::CreateSampler() {
m_sampler = CreateWrappedSampler(m_device);
void SMAA::CreateSampler(const Device& device) {
m_sampler = CreateWrappedSampler(device);
}
void SMAA::CreateShaders() {
void SMAA::CreateShaders(const Device& device) {
// These match the order of the SMAAStage enum
static constexpr std::array vert_shader_sources{
ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV),
@ -110,33 +112,33 @@ void SMAA::CreateShaders() {
};
for (size_t i = 0; i < MaxSMAAStage; i++) {
m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]);
m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]);
m_vertex_shaders[i] = CreateWrappedShaderModule(device, vert_shader_sources[i]);
m_fragment_shaders[i] = CreateWrappedShaderModule(device, frag_shader_sources[i]);
}
}
void SMAA::CreateDescriptorPool() {
void SMAA::CreateDescriptorPool(const Device& device) {
// Edge detection: 1 descriptor
// Blending weight calculation: 3 descriptors
// Neighborhood blending: 2 descriptors
// 6 descriptors, 3 descriptor sets per image
m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count);
m_descriptor_pool = CreateWrappedDescriptorPool(device, 6 * m_image_count, 3 * m_image_count);
}
void SMAA::CreateDescriptorSetLayouts() {
void SMAA::CreateDescriptorSetLayouts(const Device& device) {
m_descriptor_set_layouts[EdgeDetection] =
CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
m_descriptor_set_layouts[BlendingWeightCalculation] =
CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
m_descriptor_set_layouts[NeighborhoodBlending] =
CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
}
void SMAA::CreateDescriptorSets() {
void SMAA::CreateDescriptorSets(const Device& device) {
std::vector<VkDescriptorSetLayout> layouts(m_descriptor_set_layouts.size());
std::ranges::transform(m_descriptor_set_layouts, layouts.begin(),
[](auto& layout) { return *layout; });
@ -146,21 +148,21 @@ void SMAA::CreateDescriptorSets() {
}
}
void SMAA::CreatePipelineLayouts() {
void SMAA::CreatePipelineLayouts(const Device& device) {
for (size_t i = 0; i < MaxSMAAStage; i++) {
m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]);
m_pipeline_layouts[i] = CreateWrappedPipelineLayout(device, m_descriptor_set_layouts[i]);
}
}
void SMAA::CreatePipelines() {
void SMAA::CreatePipelines(const Device& device) {
for (size_t i = 0; i < MaxSMAAStage; i++) {
m_pipelines[i] =
CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i],
CreateWrappedPipeline(device, m_renderpasses[i], m_pipeline_layouts[i],
std::tie(m_vertex_shaders[i], m_fragment_shaders[i]));
}
}
void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
void SMAA::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;
@ -184,10 +186,10 @@ void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) {
updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend],
images.descriptor_sets[NeighborhoodBlending], 1));
m_device.GetLogical().UpdateDescriptorSets(updates, {});
device.GetLogical().UpdateDescriptorSets(updates, {});
}
void SMAA::UploadImages(Scheduler& scheduler) {
void SMAA::UploadImages(const Device& device, Scheduler& scheduler) {
if (m_images_ready) {
return;
}
@ -195,9 +197,9 @@ void SMAA::UploadImages(Scheduler& scheduler) {
static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT};
static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT};
UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent,
UploadImage(device, m_allocator, scheduler, m_static_images[Area], area_extent,
VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes));
UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent,
UploadImage(device, m_allocator, scheduler, m_static_images[Search], search_extent,
VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes));
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
@ -212,8 +214,7 @@ void SMAA::UploadImages(Scheduler& scheduler) {
m_images_ready = true;
}
void SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image,
VkImageView* inout_image_view) {
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];
VkImage input_image = *inout_image;
@ -232,8 +233,8 @@ void SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image,
*images.framebuffers[BlendingWeightCalculation];
VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending];
UploadImages(scheduler);
UpdateDescriptorSets(*inout_image_view, image_index);
UploadImages(device, scheduler);
UpdateDescriptorSets(device, *inout_image_view, image_index);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([=, this](vk::CommandBuffer cmdbuf) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -16,11 +19,10 @@ class StagingBufferPool;
class SMAA final : public AntiAliasPass {
public:
explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count,
VkExtent2D extent);
explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent);
~SMAA() override;
void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image,
void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image,
VkImageView* inout_image_view) override;
private:
@ -44,19 +46,18 @@ private:
MaxDynamicImage = 3,
};
void CreateImages();
void CreateRenderPasses();
void CreateSampler();
void CreateShaders();
void CreateDescriptorPool();
void CreateDescriptorSetLayouts();
void CreateDescriptorSets();
void CreatePipelineLayouts();
void CreatePipelines();
void UpdateDescriptorSets(VkImageView image_view, size_t image_index);
void UploadImages(Scheduler& scheduler);
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);
void CreateDescriptorSetLayouts(const Device& device);
void CreateDescriptorSets(const Device& device);
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);
const Device& m_device;
MemoryAllocator& m_allocator;
const VkExtent2D m_extent;
const u32 m_image_count;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -15,19 +18,20 @@
namespace Vulkan {
WindowAdaptPass::WindowAdaptPass(const Device& device_, VkFormat frame_format,
vk::Sampler&& sampler_, vk::ShaderModule&& fragment_shader_)
: device(device_), sampler(std::move(sampler_)), fragment_shader(std::move(fragment_shader_)) {
CreateDescriptorSetLayout();
CreatePipelineLayout();
CreateVertexShader();
CreateRenderPass(frame_format);
CreatePipelines();
WindowAdaptPass::WindowAdaptPass(const Device& device, VkFormat frame_format, vk::Sampler&& sampler_, vk::ShaderModule&& fragment_shader_)
: sampler(std::move(sampler_))
, fragment_shader(std::move(fragment_shader_))
{
CreateDescriptorSetLayout(device);
CreatePipelineLayout(device);
CreateVertexShader(device);
CreateRenderPass(device, frame_format);
CreatePipelines(device);
}
WindowAdaptPass::~WindowAdaptPass() = default;
void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index,
void WindowAdaptPass::Draw(const Device& device, RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index,
std::list<Layer>& layers,
std::span<const Tegra::FramebufferConfig> configs,
const Layout::FramebufferLayout& layout, Frame* dst) {
@ -60,7 +64,7 @@ void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, s
break;
}
layer_it->ConfigureDraw(&push_constants[i], &descriptor_sets[i], rasterizer, *sampler,
layer_it->ConfigureDraw(device, &push_constants[i], &descriptor_sets[i], rasterizer, *sampler,
image_index, configs[i], layout);
layer_it++;
}
@ -111,12 +115,12 @@ VkRenderPass WindowAdaptPass::GetRenderPass() {
return *render_pass;
}
void WindowAdaptPass::CreateDescriptorSetLayout() {
void WindowAdaptPass::CreateDescriptorSetLayout(const Device& device) {
descriptor_set_layout =
CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER});
}
void WindowAdaptPass::CreatePipelineLayout() {
void WindowAdaptPass::CreatePipelineLayout(const Device& device) {
const VkPushConstantRange range{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
@ -134,15 +138,15 @@ void WindowAdaptPass::CreatePipelineLayout() {
});
}
void WindowAdaptPass::CreateVertexShader() {
void WindowAdaptPass::CreateVertexShader(const Device& device) {
vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV);
}
void WindowAdaptPass::CreateRenderPass(VkFormat frame_format) {
void WindowAdaptPass::CreateRenderPass(const Device& device, VkFormat frame_format) {
render_pass = CreateWrappedRenderPass(device, frame_format, VK_IMAGE_LAYOUT_UNDEFINED);
}
void WindowAdaptPass::CreatePipelines() {
void WindowAdaptPass::CreatePipelines(const Device& device) {
opaque_pipeline = CreateWrappedPipeline(device, render_pass, pipeline_layout,
std::tie(vertex_shader, fragment_shader));
premultiplied_pipeline = CreateWrappedPremultipliedBlendingPipeline(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -30,7 +33,7 @@ public:
vk::ShaderModule&& fragment_shader);
~WindowAdaptPass();
void Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index,
void Draw(const Device& device, RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index,
std::list<Layer>& layers, std::span<const Tegra::FramebufferConfig> configs,
const Layout::FramebufferLayout& layout, Frame* dst);
@ -38,14 +41,12 @@ public:
VkRenderPass GetRenderPass();
private:
void CreateDescriptorSetLayout();
void CreatePipelineLayout();
void CreateVertexShader();
void CreateRenderPass(VkFormat frame_format);
void CreatePipelines();
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);
private:
const Device& device;
vk::DescriptorSetLayout descriptor_set_layout;
vk::PipelineLayout pipeline_layout;
vk::Sampler sampler;

View file

@ -188,7 +188,7 @@ void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebu
Frame* frame = present_manager.GetRenderFrame();
scheduler.RequestOutsideRenderPassOperationContext();
blit_swapchain.DrawToFrame(rasterizer, frame, framebuffers,
blit_swapchain.DrawToFrame(device, rasterizer, frame, framebuffers,
render_window.GetFramebufferLayout(), swapchain.GetImageCount(),
swapchain.GetImageViewFormat());
scheduler.Flush(*frame->render_ready);
@ -226,12 +226,12 @@ 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(layout, *f.image_view, format);
f.framebuffer = blit_capture.CreateFramebuffer(device, layout, *f.image_view, format);
return f;
}();
auto dst_buffer = CreateWrappedBuffer(memory_allocator, buffer_size, MemoryUsage::Download);
blit_capture.DrawToFrame(rasterizer, &frame, framebuffers, layout, 1, format);
blit_capture.DrawToFrame(device, rasterizer, &frame, framebuffers, layout, 1, format);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
@ -295,12 +295,12 @@ 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(
applet_frame.framebuffer = blit_applet.CreateFramebuffer(device,
VideoCore::Capture::Layout, *applet_frame.image_view, CaptureFormat);
}
scheduler.RequestOutsideRenderPassOperationContext();
blit_applet.DrawToFrame(rasterizer, &applet_frame, framebuffers, VideoCore::Capture::Layout, 1,
blit_applet.DrawToFrame(device, rasterizer, &applet_frame, framebuffers, VideoCore::Capture::Layout, 1,
CaptureFormat);
}

View file

@ -18,23 +18,26 @@
namespace Vulkan {
BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_, const Device& device_,
MemoryAllocator& memory_allocator_, PresentManager& present_manager_,
Scheduler& scheduler_, const PresentFilters& filters_)
: device_memory{device_memory_}, device{device_}, memory_allocator{memory_allocator_},
present_manager{present_manager_}, scheduler{scheduler_}, filters{filters_},
image_count{1}, image_index{0},
swapchain_view_format{VK_FORMAT_B8G8R8A8_UNORM} {}
BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_, const Device& device_, MemoryAllocator& memory_allocator_, PresentManager& present_manager_, Scheduler& scheduler_, const PresentFilters& filters_)
: device_memory{device_memory_}
, memory_allocator{memory_allocator_}
, present_manager{present_manager_}
, scheduler{scheduler_}
, filters{filters_}
, image_count{1}
, image_index{0}
, swapchain_view_format{VK_FORMAT_B8G8R8A8_UNORM}
{}
BlitScreen::~BlitScreen() = default;
void BlitScreen::WaitIdle() {
void BlitScreen::WaitIdle(const Device& device) {
present_manager.WaitPresent();
scheduler.Finish();
device.GetLogical().WaitIdle();
}
void BlitScreen::SetWindowAdaptPass() {
void BlitScreen::SetWindowAdaptPass(const Device& device) {
layers.clear();
scaling_filter = filters.get_scaling_filter();
@ -82,7 +85,7 @@ void BlitScreen::SetWindowAdaptPass() {
}
}
void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame,
void BlitScreen::DrawToFrame(const Device& device, RasterizerVulkan& rasterizer, Frame* frame,
std::span<const Tegra::FramebufferConfig> framebuffers,
const Layout::FramebufferLayout& layout,
size_t current_swapchain_image_count,
@ -107,8 +110,8 @@ void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame,
}
if (resource_update_required) {
WaitIdle();
SetWindowAdaptPass();
WaitIdle(device);
SetWindowAdaptPass(device);
if (presentation_recreate_required) {
present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format,
@ -131,22 +134,22 @@ void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame,
}
}
window_adapt->Draw(rasterizer, scheduler, image_index, layers, framebuffers, layout, frame);
window_adapt->Draw(device, rasterizer, scheduler, image_index, layers, framebuffers, layout, frame);
if (++image_index >= image_count) {
image_index = 0;
}
}
vk::Framebuffer BlitScreen::CreateFramebuffer(const Layout::FramebufferLayout& layout,
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();
SetWindowAdaptPass();
WaitIdle(device);
SetWindowAdaptPass(device);
image_index = 0;
}
@ -155,10 +158,10 @@ vk::Framebuffer BlitScreen::CreateFramebuffer(const Layout::FramebufferLayout& l
.height = layout.height,
};
return CreateFramebuffer(image_view, extent, window_adapt->GetRenderPass());
return CreateFramebuffer(device, image_view, extent, window_adapt->GetRenderPass());
}
vk::Framebuffer BlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent,
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,

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -52,23 +55,22 @@ public:
Scheduler& scheduler, const PresentFilters& filters);
~BlitScreen();
void DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame,
void DrawToFrame(const Device& device, RasterizerVulkan& rasterizer, Frame* frame,
std::span<const Tegra::FramebufferConfig> framebuffers,
const Layout::FramebufferLayout& layout, size_t current_swapchain_image_count,
VkFormat current_swapchain_view_format);
[[nodiscard]] vk::Framebuffer CreateFramebuffer(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();
void SetWindowAdaptPass();
vk::Framebuffer CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent,
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;
const Device& device;
MemoryAllocator& memory_allocator;
PresentManager& present_manager;
Scheduler& scheduler;

View file

@ -234,7 +234,7 @@ struct ConditionalRenderingResolvePushConstants {
};
} // Anonymous namespace
ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool,
ComputePass::ComputePass(const Device& device_, Scheduler& scheduler, DescriptorPool& descriptor_pool,
vk::Span<VkDescriptorSetLayoutBinding> bindings,
vk::Span<VkDescriptorUpdateTemplateEntry> templates,
const DescriptorBankInfo& bank_info,
@ -270,7 +270,7 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool,
.pipelineLayout = *layout,
.set = 0,
});
descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info);
descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, bank_info);
}
if (code.empty()) {
return;
@ -313,7 +313,7 @@ ComputePass::~ComputePass() = default;
Uint8Pass::Uint8Pass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool,
StagingBufferPool& staging_buffer_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
: ComputePass(device_, scheduler_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, {},
VULKAN_UINT8_COMP_SPV),
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
@ -355,7 +355,7 @@ QuadIndexedPass::QuadIndexedPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
: ComputePass(device_, scheduler_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(u32) * 3>, VULKAN_QUAD_INDEXED_COMP_SPV),
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
@ -416,7 +416,7 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
ConditionalRenderingResolvePass::ConditionalRenderingResolvePass(
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
: ComputePass(device_, scheduler_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(ConditionalRenderingResolvePushConstants)>,
RESOLVE_CONDITIONAL_RENDER_COMP_SPV),
@ -470,7 +470,7 @@ QueriesPrefixScanPass::QueriesPrefixScanPass(
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(
device_, descriptor_pool_, QUERIES_SCAN_DESCRIPTOR_SET_BINDINGS,
device_, scheduler_, descriptor_pool_, QUERIES_SCAN_DESCRIPTOR_SET_BINDINGS,
QUERIES_SCAN_DESCRIPTOR_UPDATE_TEMPLATE, QUERIES_SCAN_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(QueriesPrefixScanPushConstants)>,
device_.IsSubgroupFeatureSupported(VK_SUBGROUP_FEATURE_BASIC_BIT) &&
@ -547,7 +547,7 @@ ASTCDecoderPass::ASTCDecoderPass(const Device& device_, Scheduler& scheduler_,
StagingBufferPool& staging_buffer_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_,
MemoryAllocator& memory_allocator_)
: ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
: ComputePass(device_, scheduler_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(AstcPushConstants)>, ASTC_DECODER_COMP_SPV),
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
@ -746,7 +746,7 @@ BlockLinearUnswizzle3DPass::BlockLinearUnswizzle3DPass(
StagingBufferPool& staging_buffer_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(
device_, descriptor_pool_,
device_, scheduler_, descriptor_pool_,
BL3D_DESCRIPTOR_SET_BINDINGS,
BL3D_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY,
BL3D_BANK_INFO,
@ -941,7 +941,7 @@ MSAACopyPass::MSAACopyPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, descriptor_pool_, MSAA_DESCRIPTOR_SET_BINDINGS,
: ComputePass(device_, scheduler_, descriptor_pool_, MSAA_DESCRIPTOR_SET_BINDINGS,
MSAA_DESCRIPTOR_UPDATE_TEMPLATE, MSAA_BANK_INFO, {},
CONVERT_NON_MSAA_TO_MSAA_COMP_SPV),
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
@ -35,7 +35,7 @@ struct StagingBufferRef;
class ComputePass {
public:
explicit ComputePass(const Device& device, DescriptorPool& descriptor_pool,
explicit ComputePass(const Device& device, Scheduler& scheduler, DescriptorPool& descriptor_pool,
vk::Span<VkDescriptorSetLayoutBinding> bindings,
vk::Span<VkDescriptorUpdateTemplateEntry> templates,
const DescriptorBankInfo& bank_info,

View file

@ -30,7 +30,7 @@ using Shader::ImageBufferDescriptor;
using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
using Tegra::Texture::TexturePair;
ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipeline_cache_,
ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk::PipelineCache& pipeline_cache_,
DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue_,
Common::ThreadWorker* thread_worker,
@ -46,7 +46,7 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel
std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(),
uniform_buffer_sizes.begin());
auto func{[this, &descriptor_pool, shader_notify, pipeline_statistics] {
auto func{[this, &scheduler, &descriptor_pool, shader_notify, pipeline_statistics] {
DescriptorLayoutBuilder builder{device};
builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT);
@ -56,7 +56,7 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel
descriptor_update_template =
builder.CreateTemplate(*descriptor_set_layout, *pipeline_layout, uses_push_descriptor);
if (!uses_push_descriptor) {
descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, info);
descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, info);
}
const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
@ -94,7 +94,7 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel
}
if (pipeline_statistics) {
pipeline_statistics->Collect(*pipeline);
pipeline_statistics->Collect(device, *pipeline);
}
std::scoped_lock lock{build_mutex};
is_built = true;

View file

@ -31,7 +31,7 @@ class Scheduler;
class ComputePipeline {
public:
explicit ComputePipeline(const Device& device, vk::PipelineCache& pipeline_cache,
explicit ComputePipeline(const Device& device, Scheduler& scheduler, vk::PipelineCache& pipeline_cache,
DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue,
Common::ThreadWorker* thread_worker,

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
@ -125,27 +125,22 @@ vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) {
throw vk::Exception(VK_ERROR_OUT_OF_POOL_MEMORY);
}
DescriptorPool::DescriptorPool(const Device& device_, Scheduler& scheduler)
: device{device_}, master_semaphore{scheduler.GetMasterSemaphore()} {}
DescriptorPool::DescriptorPool(const Device& device_, Scheduler& scheduler) {}
DescriptorPool::~DescriptorPool() = default;
DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout,
std::span<const Shader::Info> infos) {
return Allocator(layout, MakeBankInfo(infos));
DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, std::span<const Shader::Info> infos) {
return Allocator(device, scheduler, layout, MakeBankInfo(infos));
}
DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout,
const Shader::Info& info) {
return Allocator(layout, MakeBankInfo(std::array{info}));
DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const Shader::Info& info) {
return Allocator(device, scheduler, layout, MakeBankInfo(std::array{info}));
}
DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout,
const DescriptorBankInfo& info) {
return DescriptorAllocator(device, master_semaphore, Bank(info), layout);
DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const DescriptorBankInfo& info) {
return DescriptorAllocator(device, scheduler.GetMasterSemaphore(), Bank(device, info), layout);
}
DescriptorBank& DescriptorPool::Bank(const DescriptorBankInfo& reqs) {
DescriptorBank& DescriptorPool::Bank(const Device& device, const DescriptorBankInfo& reqs) {
std::shared_lock read_lock{banks_mutex};
const auto it = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) {
return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs);

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -68,17 +71,12 @@ public:
DescriptorPool& operator=(const DescriptorPool&) = delete;
DescriptorPool(const DescriptorPool&) = delete;
DescriptorAllocator Allocator(VkDescriptorSetLayout layout,
std::span<const Shader::Info> infos);
DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const Shader::Info& info);
DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const DescriptorBankInfo& info);
DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, std::span<const Shader::Info> infos);
DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const Shader::Info& info);
DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const DescriptorBankInfo& info);
private:
DescriptorBank& Bank(const DescriptorBankInfo& reqs);
const Device& device;
MasterSemaphore& master_semaphore;
DescriptorBank& Bank(const Device& device, const DescriptorBankInfo& reqs);
std::shared_mutex banks_mutex;
std::vector<DescriptorBankInfo> bank_infos;
std::vector<std::unique_ptr<DescriptorBank>> banks;

View file

@ -276,7 +276,7 @@ GraphicsPipeline::GraphicsPipeline(
descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor);
if (!uses_push_descriptor) {
descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos);
descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, stage_infos);
}
const VkDescriptorSetLayout set_layout{*descriptor_set_layout};
@ -288,7 +288,7 @@ GraphicsPipeline::GraphicsPipeline(
Validate();
MakePipeline(render_pass);
if (pipeline_statistics) {
pipeline_statistics->Collect(*pipeline);
pipeline_statistics->Collect(device, *pipeline);
}
std::scoped_lock lock{build_mutex};

View file

@ -915,7 +915,7 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
spv_module.SetObjectNameEXT(name.c_str());
}
Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
return std::make_unique<ComputePipeline>(device, vulkan_pipeline_cache, descriptor_pool,
return std::make_unique<ComputePipeline>(device, scheduler, vulkan_pipeline_cache, descriptor_pool,
guest_descriptor_queue, thread_worker, statistics,
&shader_notify, program.info, std::move(spv_module));

View file

@ -126,16 +126,14 @@ public:
current_query = nullptr;
amend_value = 0;
accumulation_value = 0;
queries_prefix_scan_pass = std::make_unique<QueriesPrefixScanPass>(
device, scheduler, descriptor_pool, compute_pass_descriptor_queue);
queries_prefix_scan_pass.emplace(device, scheduler, descriptor_pool, compute_pass_descriptor_queue);
const VkBufferCreateInfo buffer_ci = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = 8,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
@ -592,8 +590,7 @@ private:
VideoCommon::HostQueryBase* current_query;
bool has_started{};
std::mutex flush_guard;
std::unique_ptr<QueriesPrefixScanPass> queries_prefix_scan_pass;
std::optional<QueriesPrefixScanPass> queries_prefix_scan_pass;
};
// Transform feedback queries
@ -1266,41 +1263,23 @@ private:
} // namespace
struct QueryCacheRuntimeImpl {
QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_,
Tegra::MaxwellDeviceMemoryManager& device_memory_,
Vulkan::BufferCache& buffer_cache_, const Device& device_,
const MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
StagingBufferPool& staging_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue,
DescriptorPool& descriptor_pool, TextureCache& texture_cache_)
: rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_},
device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
staging_pool{staging_pool_}, guest_streamer(0, runtime),
sample_streamer(static_cast<size_t>(QueryType::ZPassPixelCount64), runtime, rasterizer,
texture_cache_, device, scheduler, memory_allocator,
compute_pass_descriptor_queue, descriptor_pool),
tfb_streamer(static_cast<size_t>(QueryType::StreamingByteCount), runtime, device,
scheduler, memory_allocator, staging_pool),
primitives_succeeded_streamer(
static_cast<size_t>(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer,
device_memory_),
primitives_needed_minus_succeeded_streamer(
static_cast<size_t>(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u),
hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} {
QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_, Tegra::MaxwellDeviceMemoryManager& device_memory_, Vulkan::BufferCache& buffer_cache_, const Device& device_, const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, StagingBufferPool& staging_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue, DescriptorPool& descriptor_pool, TextureCache& texture_cache_)
: rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_}
, device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}
, staging_pool{staging_pool_}, guest_streamer(0, runtime)
, sample_streamer(size_t(QueryType::ZPassPixelCount64), runtime, rasterizer, texture_cache_, device, scheduler, memory_allocator, compute_pass_descriptor_queue, descriptor_pool)
, tfb_streamer(size_t(QueryType::StreamingByteCount), runtime, device, scheduler, memory_allocator, staging_pool)
, primitives_succeeded_streamer(size_t(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer, device_memory_)
, primitives_needed_minus_succeeded_streamer(size_t(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u)
, hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} {
hcr_setup.sType = VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT;
hcr_setup.pNext = nullptr;
hcr_setup.flags = 0;
const bool has_conditional_rendering = device.IsExtConditionalRendering();
if (has_conditional_rendering) {
conditional_resolve_pass = std::make_unique<ConditionalRenderingResolvePass>(
device, scheduler, descriptor_pool, compute_pass_descriptor_queue);
}
VkBufferUsageFlags hcr_buffer_usage =
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
if (has_conditional_rendering) {
VkBufferUsageFlags hcr_buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
if (device.IsExtConditionalRendering()) {
conditional_resolve_pass.emplace(device, scheduler, descriptor_pool, compute_pass_descriptor_queue);
hcr_buffer_usage |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT;
}
@ -1339,7 +1318,7 @@ struct QueryCacheRuntimeImpl {
std::vector<std::vector<VkBufferCopy>> copies_setup;
// Host conditional rendering data
std::unique_ptr<ConditionalRenderingResolvePass> conditional_resolve_pass;
std::optional<ConditionalRenderingResolvePass> conditional_resolve_pass;
vk::Buffer hcr_resolve_buffer;
VkConditionalRenderingBeginInfoEXT hcr_setup;
VkBuffer hcr_buffer;
@ -1351,13 +1330,7 @@ struct QueryCacheRuntimeImpl {
Maxwell3D* maxwell3d;
};
QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer,
Tegra::MaxwellDeviceMemoryManager& device_memory_,
Vulkan::BufferCache& buffer_cache_, const Device& device_,
const MemoryAllocator& memory_allocator_,
Scheduler& scheduler_, StagingBufferPool& staging_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue,
DescriptorPool& descriptor_pool, TextureCache& texture_cache_) {
QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, Tegra::MaxwellDeviceMemoryManager& device_memory_, Vulkan::BufferCache& buffer_cache_, const Device& device_, const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, StagingBufferPool& staging_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue, DescriptorPool& descriptor_pool, TextureCache& texture_cache_) {
impl = std::make_unique<QueryCacheRuntimeImpl>(
*this, rasterizer, device_memory_, buffer_cache_, device_, memory_allocator_, scheduler_,
staging_pool_, compute_pass_descriptor_queue, descriptor_pool, texture_cache_);
@ -1686,8 +1659,7 @@ void QueryCacheRuntime::SyncValues(std::span<SyncValuesType> values, VkBuffer ba
}
impl->scheduler.RequestOutsideRenderPassOperationContext();
impl->scheduler.Record([src_buffer, dst_buffers = std::move(impl->buffers_to_upload_to),
vk_copies = std::move(impl->copies_setup)](vk::CommandBuffer cmdbuf) {
impl->scheduler.Record([src_buffer, dst_buffers = std::move(impl->buffers_to_upload_to), vk_copies = std::move(impl->copies_setup)](vk::CommandBuffer cmdbuf) {
size_t size = dst_buffers.size();
for (size_t i = 0; i < size; i++) {
cmdbuf.CopyBuffer(src_buffer, dst_buffers[i].first, vk_copies[i]);

View file

@ -235,7 +235,7 @@ void SetupRasterModes(Maxwell3D::DirtyState::Tables &tables) {
} // Anonymous namespace
void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) {
auto& tables{channel_state.maxwell_3d->dirty.tables};
auto& tables{channel_state.payload->maxwell_3d.dirty.tables};
SetupDirtyFlags(tables);
SetupDirtyViewports(tables);
SetupDirtyScissors(tables);
@ -258,7 +258,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) {
}
void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) {
flags = &channel_state.maxwell_3d->dirty.flags;
flags = &channel_state.payload->maxwell_3d.dirty.flags;
}
void StateTracker::InvalidateState() {

View file

@ -1,10 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <variant>
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
@ -12,20 +15,15 @@ namespace Vulkan {
class Device;
class Scheduler;
struct DescriptorUpdateEntry {
struct Empty {};
union DescriptorUpdateEntry {
DescriptorUpdateEntry() = default;
DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {}
DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {}
DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {}
union {
Empty empty{};
VkDescriptorImageInfo image;
VkDescriptorBufferInfo buffer;
VkBufferView texel_buffer;
};
std::monostate empty{};
VkDescriptorImageInfo image;
VkDescriptorBufferInfo buffer;
VkBufferView texel_buffer;
};
class UpdateDescriptorQueue final {