From 18b012c148dfd9096fec8da8cb3f611da7ee5631 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 24 Sep 2025 17:43:23 +0000 Subject: [PATCH 1/7] [vk, ogl/IR, dynarmic/IR] friendlier IR identity pointer chasing, inline AA passes Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/ir/opt_passes.cpp | 34 +++++------ .../ir_opt/identity_removal_pass.cpp | 29 +++++---- .../renderer_opengl/present/layer.cpp | 19 +++--- .../renderer_opengl/present/layer.h | 14 ++--- .../renderer_vulkan/present/anti_alias_pass.h | 6 -- .../renderer_vulkan/present/filters.cpp | 39 +++++------- .../renderer_vulkan/present/fsr.cpp | 59 +++++++------------ .../renderer_vulkan/present/layer.cpp | 28 +++++---- .../renderer_vulkan/present/layer.h | 13 ++-- 9 files changed, 106 insertions(+), 135 deletions(-) diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index 844e29023c..18323936d9 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -1226,32 +1226,28 @@ static void DeadCodeElimination(IR::Block& block) { } static void IdentityRemovalPass(IR::Block& block) { - boost::container::small_vector to_invalidate; - - auto iter = block.begin(); - while (iter != block.end()) { - IR::Inst& inst = *iter; - - const size_t num_args = inst.NumArgs(); - for (size_t i = 0; i < num_args; i++) { - while (true) { - IR::Value arg = inst.GetArg(i); - if (!arg.IsIdentity()) - break; - inst.SetArg(i, arg.GetInst()->GetArg(0)); + boost::container::small_vector to_invalidate; + for (auto it = block.begin(); it != block.end();) { + const size_t num_args = it->NumArgs(); + for (size_t i = 0; i < num_args; ++i) { + IR::Value arg = it->GetArg(i); + if (arg.IsIdentity()) { + do { + arg = arg.GetInst()->GetArg(0); + } while (arg.IsIdentity()); + it->SetArg(i, arg); } } - if (inst.GetOpcode() == IR::Opcode::Identity || inst.GetOpcode() == IR::Opcode::Void) { - iter = block.Instructions().erase(inst); - to_invalidate.push_back(&inst); + if (it->GetOpcode() == IR::Opcode::Identity || it->GetOpcode() == IR::Opcode::Void) { + to_invalidate.push_back(&*it); + it = block.Instructions().erase(it); } else { - ++iter; + ++it; } } - for (IR::Inst* inst : to_invalidate) { + for (IR::Inst* const inst : to_invalidate) inst->Invalidate(); - } } static void NamingPass(IR::Block& block) { diff --git a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp index 951534bbf2..18e3553010 100644 --- a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp +++ b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/value.h" @@ -10,28 +11,30 @@ namespace Shader::Optimization { void IdentityRemovalPass(IR::Program& program) { - std::vector to_invalidate; + boost::container::small_vector to_invalidate; for (IR::Block* const block : program.blocks) { - for (auto inst = block->begin(); inst != block->end();) { - const size_t num_args{inst->NumArgs()}; + for (auto it = block->begin(); it != block->end();) { + const size_t num_args{it->NumArgs()}; for (size_t i = 0; i < num_args; ++i) { - IR::Value arg; - while ((arg = inst->Arg(i)).IsIdentity()) { - inst->SetArg(i, arg.Inst()->Arg(0)); + IR::Value arg = it->Arg(i); + if (arg.IsIdentity()) { + do { // Pointer chasing (3-derefs) + arg = arg.Inst()->Arg(0); + } while (arg.IsIdentity()); + it->SetArg(i, arg); } } - if (inst->GetOpcode() == IR::Opcode::Identity || - inst->GetOpcode() == IR::Opcode::Void) { - to_invalidate.push_back(&*inst); - inst = block->Instructions().erase(inst); + + if (it->GetOpcode() == IR::Opcode::Identity || it->GetOpcode() == IR::Opcode::Void) { + to_invalidate.push_back(&*it); + it = block->Instructions().erase(it); } else { - ++inst; + ++it; } } } - for (IR::Inst* const inst : to_invalidate) { + for (IR::Inst* const inst : to_invalidate) inst->Invalidate(); - } } } // namespace Shader::Optimization diff --git a/src/video_core/renderer_opengl/present/layer.cpp b/src/video_core/renderer_opengl/present/layer.cpp index 6c7092d229..6ce4ffa1ff 100644 --- a/src/video_core/renderer_opengl/present/layer.cpp +++ b/src/video_core/renderer_opengl/present/layer.cpp @@ -54,12 +54,12 @@ GLuint Layer::ConfigureDraw(std::array& out_matrix, switch (anti_aliasing) { case Settings::AntiAliasing::Fxaa: CreateFXAA(); - texture = fxaa->Draw(program_manager, info.display_texture); + texture = std::get(anti_alias).Draw(program_manager, info.display_texture); break; case Settings::AntiAliasing::Smaa: default: CreateSMAA(); - texture = smaa->Draw(program_manager, info.display_texture); + texture = std::get(anti_alias).Draw(program_manager, info.display_texture); break; } } @@ -68,7 +68,7 @@ GLuint Layer::ConfigureDraw(std::array& out_matrix, if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { if (!fsr || fsr->NeedsRecreation(layout.screen)) { - fsr = std::make_unique(layout.screen.GetWidth(), layout.screen.GetHeight()); + fsr.emplace(layout.screen.GetWidth(), layout.screen.GetHeight()); } texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop); @@ -199,23 +199,20 @@ void Layer::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuf glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format, framebuffer_texture.width, framebuffer_texture.height); - fxaa.reset(); - smaa.reset(); + anti_alias.emplace(); } void Layer::CreateFXAA() { - smaa.reset(); - if (!fxaa) { - fxaa = std::make_unique( + if (!std::holds_alternative(anti_alias)) { + anti_alias.emplace( Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); } } void Layer::CreateSMAA() { - fxaa.reset(); - if (!smaa) { - smaa = std::make_unique( + if (!std::holds_alternative(anti_alias)) { + anti_alias.emplace( Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); } diff --git a/src/video_core/renderer_opengl/present/layer.h b/src/video_core/renderer_opengl/present/layer.h index 5b15b730fc..a4ebed963c 100644 --- a/src/video_core/renderer_opengl/present/layer.h +++ b/src/video_core/renderer_opengl/present/layer.h @@ -3,11 +3,15 @@ #pragma once -#include +#include +#include #include #include "video_core/host1x/gpu_device_memory_manager.h" #include "video_core/renderer_opengl/gl_resource_manager.h" +#include "video_core/renderer_opengl/present/smaa.h" +#include "video_core/renderer_opengl/present/fxaa.h" +#include "video_core/renderer_opengl/present/fsr.h" namespace Layout { struct FramebufferLayout; @@ -26,11 +30,8 @@ struct FramebufferConfig; namespace OpenGL { struct FramebufferTextureInfo; -class FSR; -class FXAA; class ProgramManager; class RasterizerOpenGL; -class SMAA; /// Structure used for storing information about the textures for the Switch screen struct TextureInfo { @@ -76,9 +77,8 @@ private: /// Display information for Switch screen TextureInfo framebuffer_texture; - std::unique_ptr fsr; - std::unique_ptr fxaa; - std::unique_ptr smaa; + std::optional fsr; + std::variant anti_alias; }; } // namespace OpenGL diff --git a/src/video_core/renderer_vulkan/present/anti_alias_pass.h b/src/video_core/renderer_vulkan/present/anti_alias_pass.h index 1f20fbd7f0..db7bdacd1d 100644 --- a/src/video_core/renderer_vulkan/present/anti_alias_pass.h +++ b/src/video_core/renderer_vulkan/present/anti_alias_pass.h @@ -16,10 +16,4 @@ public: VkImageView* inout_image_view) = 0; }; -class NoAA final : public AntiAliasPass { -public: - void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, - VkImageView* inout_image_view) override {} -}; - } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/filters.cpp b/src/video_core/renderer_vulkan/present/filters.cpp index e0f2b26f84..381031fe6e 100644 --- a/src/video_core/renderer_vulkan/present/filters.cpp +++ b/src/video_core/renderer_vulkan/present/filters.cpp @@ -24,61 +24,52 @@ namespace Vulkan { -namespace { - -vk::ShaderModule SelectScaleForceShader(const Device& device) { - if (device.IsFloat16Supported()) { - return BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FP16_FRAG_SPV); - } else { - return BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FP32_FRAG_SPV); - } -} - -} // Anonymous namespace - std::unique_ptr MakeNearestNeighbor(const Device& device, VkFormat frame_format) { - return std::make_unique(device, frame_format, - CreateNearestNeighborSampler(device), - BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); + return std::make_unique(device, frame_format, CreateNearestNeighborSampler(device), + BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); } std::unique_ptr MakeBilinear(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); + BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); } std::unique_ptr MakeSpline1(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_SPLINE1_FRAG_SPV)); + BuildShader(device, PRESENT_SPLINE1_FRAG_SPV)); } std::unique_ptr MakeBicubic(const Device& device, VkFormat frame_format) { // No need for handrolled shader -- if the VK impl can do it for us ;) if (device.IsExtFilterCubicSupported()) return std::make_unique(device, frame_format, CreateCubicSampler(device), - BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); + BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_BICUBIC_FRAG_SPV)); + BuildShader(device, PRESENT_BICUBIC_FRAG_SPV)); } std::unique_ptr MakeGaussian(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV)); + BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV)); } std::unique_ptr MakeLanczos(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_LANCZOS_FRAG_SPV)); + BuildShader(device, PRESENT_LANCZOS_FRAG_SPV)); } std::unique_ptr MakeScaleForce(const Device& device, VkFormat frame_format) { - return std::make_unique(device, frame_format, CreateBilinearSampler(device), - SelectScaleForceShader(device)); + auto const select_fn = [&]() { + return device.IsFloat16Supported() + ? BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FP16_FRAG_SPV) + : BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FP32_FRAG_SPV); + }; + return std::make_unique(device, frame_format, CreateBilinearSampler(device), select_fn()); } std::unique_ptr MakeArea(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_AREA_FRAG_SPV)); + BuildShader(device, PRESENT_AREA_FRAG_SPV)); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/fsr.cpp b/src/video_core/renderer_vulkan/present/fsr.cpp index 3f708be704..b2d35cbe97 100644 --- a/src/video_core/renderer_vulkan/present/fsr.cpp +++ b/src/video_core/renderer_vulkan/present/fsr.cpp @@ -41,25 +41,18 @@ FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_c void FSR::CreateImages() { 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.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); } } void FSR::CreateRenderPasses() { m_renderpass = CreateWrappedRenderPass(m_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(m_device, m_renderpass, images.image_views[Easu], m_extent); + images.framebuffers[Rcas] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Rcas], m_extent); } } @@ -87,16 +80,13 @@ void FSR::CreateDescriptorPool() { } void FSR::CreateDescriptorSetLayout() { - m_descriptor_set_layout = - CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); + m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } void FSR::CreateDescriptorSets() { std::vector layouts(MaxFsrStage, *m_descriptor_set_layout); - - for (auto& images : m_dynamic_images) { + for (auto& images : m_dynamic_images) images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); - } } void FSR::CreatePipelineLayouts() { @@ -128,31 +118,24 @@ void FSR::CreatePipelines() { void FSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; - std::vector updates; - image_infos.reserve(2); - - updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, - images.descriptor_sets[Easu], 0)); - updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Easu], - images.descriptor_sets[Rcas], 0)); - + std::vector 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) + }; m_device.GetLogical().UpdateDescriptorSets(updates, {}); } void FSR::UploadImages(Scheduler& scheduler) { - if (m_images_ready) { - return; + if (!m_images_ready) { + m_images_ready = true; + scheduler.Record([&](vk::CommandBuffer cmdbuf) { + for (auto& image : m_dynamic_images) { + ClearColorImage(cmdbuf, *image.images[Easu]); + ClearColorImage(cmdbuf, *image.images[Rcas]); + } + }); + scheduler.Finish(); } - - scheduler.Record([&](vk::CommandBuffer cmdbuf) { - for (auto& image : m_dynamic_images) { - ClearColorImage(cmdbuf, *image.images[Easu]); - ClearColorImage(cmdbuf, *image.images[Rcas]); - } - }); - scheduler.Finish(); - - m_images_ready = true; } VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index fa7c457573..9946335fa3 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -4,7 +4,12 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include "video_core/present.h" +#include "video_core/renderer_vulkan/present/anti_alias_pass.h" +/* X11 defines */ +#undef Success +#undef BadValue #include "video_core/renderer_vulkan/vk_rasterizer.h" #include "common/settings.h" @@ -58,7 +63,7 @@ Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Schedule CreateDescriptorPool(); CreateDescriptorSets(layout); if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { - CreateFSR(output_size); + fsr.emplace(device, memory_allocator, image_count, output_size); } } @@ -97,7 +102,11 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, VkImageView source_image_view = texture_info ? texture_info->image_view : *raw_image_views[image_index]; - anti_alias->Draw(scheduler, image_index, &source_image, &source_image_view); + if (std::holds_alternative(anti_alias)) { + std::get(anti_alias).Draw(scheduler, image_index, &source_image, &source_image_view); + } else if (std::holds_alternative(anti_alias)) { + std::get(anti_alias).Draw(scheduler, image_index, &source_image, &source_image_view); + } auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); const VkExtent2D render_extent{ @@ -156,10 +165,6 @@ void Layer::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { } } -void Layer::CreateFSR(VkExtent2D output_size) { - fsr = std::make_unique(device, memory_allocator, image_count, output_size); -} - void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { if (framebuffer.width == raw_width && framebuffer.height == raw_height && framebuffer.pixel_format == pixel_format && !raw_images.empty()) { @@ -169,7 +174,7 @@ void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { raw_width = framebuffer.width; raw_height = framebuffer.height; pixel_format = framebuffer.pixel_format; - anti_alias.reset(); + anti_alias.emplace(); ReleaseRawImages(); CreateStagingBuffer(framebuffer); @@ -177,9 +182,8 @@ void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { } void Layer::SetAntiAliasPass() { - if (anti_alias && anti_alias_setting == filters.get_anti_aliasing()) { + if (!std::holds_alternative(anti_alias) && anti_alias_setting == filters.get_anti_aliasing()) return; - } anti_alias_setting = filters.get_anti_aliasing(); @@ -190,13 +194,13 @@ void Layer::SetAntiAliasPass() { switch (anti_alias_setting) { case Settings::AntiAliasing::Fxaa: - anti_alias = std::make_unique(device, memory_allocator, image_count, render_area); + anti_alias.emplace(device, memory_allocator, image_count, render_area); break; case Settings::AntiAliasing::Smaa: - anti_alias = std::make_unique(device, memory_allocator, image_count, render_area); + anti_alias.emplace(device, memory_allocator, image_count, render_area); break; default: - anti_alias = std::make_unique(); + anti_alias.emplace(); break; } } diff --git a/src/video_core/renderer_vulkan/present/layer.h b/src/video_core/renderer_vulkan/present/layer.h index f5effdcd7f..6b8fed60ec 100644 --- a/src/video_core/renderer_vulkan/present/layer.h +++ b/src/video_core/renderer_vulkan/present/layer.h @@ -3,9 +3,15 @@ #pragma once +#include +#include + #include "common/math_util.h" #include "video_core/host1x/gpu_device_memory_manager.h" #include "video_core/vulkan_common/vulkan_wrapper.h" +#include "video_core/renderer_vulkan/present/fsr.h" +#include "video_core/renderer_vulkan/present/fxaa.h" +#include "video_core/renderer_vulkan/present/smaa.h" namespace Layout { struct FramebufferLayout; @@ -29,7 +35,6 @@ namespace Vulkan { class AntiAliasPass; class Device; -class FSR; class MemoryAllocator; struct PresentPushConstants; class RasterizerVulkan; @@ -54,7 +59,6 @@ private: void CreateDescriptorSets(VkDescriptorSetLayout layout); void CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer); void CreateRawImages(const Tegra::FramebufferConfig& framebuffer); - void CreateFSR(VkExtent2D output_size); void RefreshResources(const Tegra::FramebufferConfig& framebuffer); void SetAntiAliasPass(); @@ -87,9 +91,8 @@ private: Service::android::PixelFormat pixel_format{}; Settings::AntiAliasing anti_alias_setting{}; - std::unique_ptr anti_alias{}; - - std::unique_ptr fsr{}; + std::variant anti_alias{}; + std::optional fsr{}; std::vector resource_ticks{}; }; From 298df9d342ef980a03f5fcc9dbcc56eb516717ea Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 24 Sep 2025 17:47:12 +0000 Subject: [PATCH 2/7] Fix license Signed-off-by: lizzie --- src/shader_recompiler/ir_opt/identity_removal_pass.cpp | 3 +++ src/video_core/renderer_opengl/present/layer.cpp | 3 +++ src/video_core/renderer_opengl/present/layer.h | 3 +++ src/video_core/renderer_vulkan/present/anti_alias_pass.h | 3 +++ src/video_core/renderer_vulkan/present/fsr.cpp | 3 +++ src/video_core/renderer_vulkan/present/layer.h | 3 +++ 6 files changed, 18 insertions(+) diff --git a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp index 18e3553010..68f8a9ec44 100644 --- a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp +++ b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_opengl/present/layer.cpp b/src/video_core/renderer_opengl/present/layer.cpp index 6ce4ffa1ff..f18600e692 100644 --- a/src/video_core/renderer_opengl/present/layer.cpp +++ b/src/video_core/renderer_opengl/present/layer.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_opengl/present/layer.h b/src/video_core/renderer_opengl/present/layer.h index a4ebed963c..e09fd6f696 100644 --- a/src/video_core/renderer_opengl/present/layer.h +++ b/src/video_core/renderer_opengl/present/layer.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_vulkan/present/anti_alias_pass.h b/src/video_core/renderer_vulkan/present/anti_alias_pass.h index db7bdacd1d..b7d3e2de15 100644 --- a/src/video_core/renderer_vulkan/present/anti_alias_pass.h +++ b/src/video_core/renderer_vulkan/present/anti_alias_pass.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_vulkan/present/fsr.cpp b/src/video_core/renderer_vulkan/present/fsr.cpp index b2d35cbe97..24fc61e813 100644 --- a/src/video_core/renderer_vulkan/present/fsr.cpp +++ b/src/video_core/renderer_vulkan/present/fsr.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_vulkan/present/layer.h b/src/video_core/renderer_vulkan/present/layer.h index 6b8fed60ec..062b7792c4 100644 --- a/src/video_core/renderer_vulkan/present/layer.h +++ b/src/video_core/renderer_vulkan/present/layer.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 From cc50571275cd09196ae60ade262d802a96fdd96b Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 27 Sep 2025 20:41:52 +0200 Subject: [PATCH 3/7] [dynarmic] fix tests builds (#2601) This fixes tests for dynarmic, print_info and test_generator. Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2601 Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: lizzie Co-committed-by: lizzie --- src/dynarmic/tests/A32/fuzz_arm.cpp | 5 ++-- src/dynarmic/tests/A32/fuzz_thumb.cpp | 1 + .../tests/A32/test_arm_instructions.cpp | 4 +++ src/dynarmic/tests/A32/test_coprocessor.cpp | 4 +++ src/dynarmic/tests/A32/test_svc.cpp | 4 +++ .../tests/A32/test_thumb_instructions.cpp | 1 + src/dynarmic/tests/A32/testenv.h | 1 - src/dynarmic/tests/A64/a64.cpp | 4 +++ src/dynarmic/tests/A64/fp_min_max.cpp | 1 + src/dynarmic/tests/A64/fuzz_with_unicorn.cpp | 1 + .../tests/A64/misaligned_page_table.cpp | 4 +++ src/dynarmic/tests/A64/real_world.cpp | 1 + src/dynarmic/tests/A64/test_invalidation.cpp | 4 +++ src/dynarmic/tests/A64/testenv.h | 1 - src/dynarmic/tests/decoder_tests.cpp | 26 ++++++----------- src/dynarmic/tests/native/preserve_xmm.cpp | 1 + src/dynarmic/tests/print_info.cpp | 29 +++++++++---------- 17 files changed, 56 insertions(+), 36 deletions(-) diff --git a/src/dynarmic/tests/A32/fuzz_arm.cpp b/src/dynarmic/tests/A32/fuzz_arm.cpp index 087ce54813..bef473a491 100644 --- a/src/dynarmic/tests/A32/fuzz_arm.cpp +++ b/src/dynarmic/tests/A32/fuzz_arm.cpp @@ -24,6 +24,7 @@ #include "../rand_int.h" #include "../unicorn_emu/a32_unicorn.h" #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/llvm_disassemble.h" @@ -46,7 +47,7 @@ using namespace Dynarmic; template bool AnyLocationDescriptorForTerminalHas(IR::Terminal terminal, Fn fn) { - return Common::VisitVariant(terminal, [&](auto t) -> bool { + return boost::apply_visitor([&](auto t) -> bool { using T = std::decay_t; if constexpr (std::is_same_v) { return false; @@ -72,7 +73,7 @@ bool AnyLocationDescriptorForTerminalHas(IR::Terminal terminal, Fn fn) { ASSERT_MSG(false, "Invalid terminal type"); return false; } - }); + }, terminal); } bool ShouldTestInst(u32 instruction, u32 pc, bool is_thumb, bool is_last_inst, A32::ITState it_state = {}) { diff --git a/src/dynarmic/tests/A32/fuzz_thumb.cpp b/src/dynarmic/tests/A32/fuzz_thumb.cpp index ad01e5718b..7f64cb0ccb 100644 --- a/src/dynarmic/tests/A32/fuzz_thumb.cpp +++ b/src/dynarmic/tests/A32/fuzz_thumb.cpp @@ -22,6 +22,7 @@ #include "../rand_int.h" #include "../unicorn_emu/a32_unicorn.h" #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/frontend/A32/FPSCR.h" #include "dynarmic/frontend/A32/PSR.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" diff --git a/src/dynarmic/tests/A32/test_arm_instructions.cpp b/src/dynarmic/tests/A32/test_arm_instructions.cpp index 0411877823..2e7e7dc5d8 100644 --- a/src/dynarmic/tests/A32/test_arm_instructions.cpp +++ b/src/dynarmic/tests/A32/test_arm_instructions.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD @@ -6,6 +9,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/interface/A32/a32.h" diff --git a/src/dynarmic/tests/A32/test_coprocessor.cpp b/src/dynarmic/tests/A32/test_coprocessor.cpp index 98da0e5d34..3888d2c68b 100644 --- a/src/dynarmic/tests/A32/test_coprocessor.cpp +++ b/src/dynarmic/tests/A32/test_coprocessor.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -8,6 +11,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/interface/A32/a32.h" #include "dynarmic/interface/A32/coprocessor.h" diff --git a/src/dynarmic/tests/A32/test_svc.cpp b/src/dynarmic/tests/A32/test_svc.cpp index 8b55d6537c..0be2432c7b 100644 --- a/src/dynarmic/tests/A32/test_svc.cpp +++ b/src/dynarmic/tests/A32/test_svc.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -8,6 +11,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A32/test_thumb_instructions.cpp b/src/dynarmic/tests/A32/test_thumb_instructions.cpp index 3501d5419f..d509acdd8d 100644 --- a/src/dynarmic/tests/A32/test_thumb_instructions.cpp +++ b/src/dynarmic/tests/A32/test_thumb_instructions.cpp @@ -10,6 +10,7 @@ #include "dynarmic/common/common_types.h" #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/interface/A32/a32.h" static Dynarmic::A32::UserConfig GetUserConfig(ThumbTestEnv* testenv) { diff --git a/src/dynarmic/tests/A32/testenv.h b/src/dynarmic/tests/A32/testenv.h index a6df2017ce..72eaafce14 100644 --- a/src/dynarmic/tests/A32/testenv.h +++ b/src/dynarmic/tests/A32/testenv.h @@ -17,7 +17,6 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" #include "dynarmic/interface/A32/a32.h" -#include "../native/testenv.h" template class A32TestEnv : public Dynarmic::A32::UserCallbacks { diff --git a/src/dynarmic/tests/A64/a64.cpp b/src/dynarmic/tests/A64/a64.cpp index 40eff1f071..bc51eca164 100644 --- a/src/dynarmic/tests/A64/a64.cpp +++ b/src/dynarmic/tests/A64/a64.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -7,6 +10,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/interface/exclusive_monitor.h" diff --git a/src/dynarmic/tests/A64/fp_min_max.cpp b/src/dynarmic/tests/A64/fp_min_max.cpp index d8b45db807..1669b63071 100644 --- a/src/dynarmic/tests/A64/fp_min_max.cpp +++ b/src/dynarmic/tests/A64/fp_min_max.cpp @@ -12,6 +12,7 @@ #include "dynarmic/common/common_types.h" #include "./testenv.h" +#include "../native/testenv.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp index 1c3531ebc5..2fb5a7b35e 100644 --- a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp +++ b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp @@ -19,6 +19,7 @@ #include "../rand_int.h" #include "../unicorn_emu/a64_unicorn.h" #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/llvm_disassemble.h" diff --git a/src/dynarmic/tests/A64/misaligned_page_table.cpp b/src/dynarmic/tests/A64/misaligned_page_table.cpp index 8235e14a67..fc0bc77428 100644 --- a/src/dynarmic/tests/A64/misaligned_page_table.cpp +++ b/src/dynarmic/tests/A64/misaligned_page_table.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -6,6 +9,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/interface/A64/a64.h" TEST_CASE("misaligned load/store do not use page_table when detect_misaligned_access_via_page_table is set", "[a64]") { diff --git a/src/dynarmic/tests/A64/real_world.cpp b/src/dynarmic/tests/A64/real_world.cpp index 07532d95af..a083f16d61 100644 --- a/src/dynarmic/tests/A64/real_world.cpp +++ b/src/dynarmic/tests/A64/real_world.cpp @@ -5,6 +5,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/interface/A64/a64.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/test_invalidation.cpp b/src/dynarmic/tests/A64/test_invalidation.cpp index 168043c1cb..0c92f5f606 100644 --- a/src/dynarmic/tests/A64/test_invalidation.cpp +++ b/src/dynarmic/tests/A64/test_invalidation.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -6,6 +9,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/interface/A64/a64.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/testenv.h b/src/dynarmic/tests/A64/testenv.h index 31e338b138..fcdadb23e6 100644 --- a/src/dynarmic/tests/A64/testenv.h +++ b/src/dynarmic/tests/A64/testenv.h @@ -12,7 +12,6 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" #include "dynarmic/interface/A64/a64.h" -#include "../native/testenv.h" using Vector = Dynarmic::A64::Vector; diff --git a/src/dynarmic/tests/decoder_tests.cpp b/src/dynarmic/tests/decoder_tests.cpp index e545309960..cdd2c70cd9 100644 --- a/src/dynarmic/tests/decoder_tests.cpp +++ b/src/dynarmic/tests/decoder_tests.cpp @@ -36,22 +36,12 @@ TEST_CASE("ASIMD Decoder: Ensure table order correctness", "[decode][a32][.]") { const auto is_decode_error = [&get_ir](const A32::ASIMDMatcher& matcher, u32 instruction) { const auto block = get_ir(matcher, instruction); - - for (const auto& ir_inst : block) { - if (ir_inst.GetOpcode() == IR::Opcode::A32ExceptionRaised) { - if (static_cast(ir_inst.GetArg(1).GetU64()) == A32::Exception::DecodeError) { - return true; - } - } - } - return false; + return std::find_if(block.cbegin(), block.cend(), [](auto const& e) { + return e.GetOpcode() == IR::Opcode::A32ExceptionRaised && A32::Exception(e.GetArg(1).GetU64()) == A32::Exception::DecodeError; + }) != block.cend(); }; for (auto iter = table.cbegin(); iter != table.cend(); ++iter) { - if (std::strncmp(iter->GetName(), "UNALLOCATED", 11) == 0) { - continue; - } - const u32 expect = iter->GetExpected(); const u32 mask = iter->GetMask(); u32 x = 0; @@ -59,15 +49,17 @@ TEST_CASE("ASIMD Decoder: Ensure table order correctness", "[decode][a32][.]") { const u32 instruction = expect | x; const bool iserr = is_decode_error(*iter, instruction); - const auto alternative = std::find_if(table.cbegin(), iter, [instruction](const auto& m) { return m.Matches(instruction); }); + const auto alternative = std::find_if(table.cbegin(), iter, [instruction](const auto& m) { + return m.Matches(instruction); + }); const bool altiserr = is_decode_error(*alternative, instruction); INFO("Instruction: " << std::hex << std::setfill('0') << std::setw(8) << instruction); INFO("Expect: " << std::hex << std::setfill('0') << std::setw(8) << expect); INFO("Fill: " << std::hex << std::setfill('0') << std::setw(8) << x); - INFO("Name: " << iter->GetName()); + //INFO("Name: " << *A32::GetNameASIMD(instruction)); INFO("iserr: " << iserr); - INFO("alternative: " << alternative->GetName()); + //INFO("alternative: " << alternative->GetName()); INFO("altiserr: " << altiserr); REQUIRE(((!iserr && alternative == iter) || (iserr && alternative != iter && !altiserr))); @@ -75,4 +67,4 @@ TEST_CASE("ASIMD Decoder: Ensure table order correctness", "[decode][a32][.]") { x = ((x | mask) + 1) & ~mask; } while (x != 0); } -} +} \ No newline at end of file diff --git a/src/dynarmic/tests/native/preserve_xmm.cpp b/src/dynarmic/tests/native/preserve_xmm.cpp index 0f69697b7a..7421252063 100644 --- a/src/dynarmic/tests/native/preserve_xmm.cpp +++ b/src/dynarmic/tests/native/preserve_xmm.cpp @@ -6,6 +6,7 @@ #include #include "../A64/testenv.h" +#include "../native/testenv.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/interface/exclusive_monitor.h" diff --git a/src/dynarmic/tests/print_info.cpp b/src/dynarmic/tests/print_info.cpp index 4b6c951c03..3d1268f467 100644 --- a/src/dynarmic/tests/print_info.cpp +++ b/src/dynarmic/tests/print_info.cpp @@ -32,27 +32,26 @@ #include "dynarmic/frontend/A64/translate/a64_translate.h" #include "dynarmic/frontend/A64/translate/impl/impl.h" #include "dynarmic/interface/A32/a32.h" +#include "dynarmic/interface/A32/config.h" #include "dynarmic/interface/A32/disassembler.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/opt_passes.h" using namespace Dynarmic; -const char* GetNameOfA32Instruction(u32 instruction) { - if (auto vfp_decoder = A32::DecodeVFP(instruction)) { - return vfp_decoder->get().GetName(); - } else if (auto asimd_decoder = A32::DecodeASIMD(instruction)) { - return asimd_decoder->get().GetName(); - } else if (auto decoder = A32::DecodeArm(instruction)) { - return decoder->get().GetName(); - } +std::string_view GetNameOfA32Instruction(u32 instruction) { + //if (auto const vfp_decoder = A32::DecodeVFP(instruction)) + // return *A32::GetNameVFP(instruction); + //else if (auto const asimd_decoder = A32::DecodeASIMD(instruction)) + // return *A32::GetNameASIMD(instruction); + //else if (auto const decoder = A32::DecodeArm(instruction)) + // return *A32::GetNameARM(instruction); return ""; } -const char* GetNameOfA64Instruction(u32 instruction) { - if (auto decoder = A64::Decode(instruction)) { - return decoder->get().GetName(); - } +std::string_view GetNameOfA64Instruction(u32 instruction) { + //if (auto const decoder = A64::Decode(instruction)) + // return *A64::GetName(instruction); return ""; } @@ -66,7 +65,7 @@ void PrintA32Instruction(u32 instruction) { fmt::print("should_continue: {}\n\n", should_continue); fmt::print("IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); - Optimization::Optimize(ir_block, conf, {}); + Optimization::Optimize(ir_block, A32::UserConfig{}, {}); fmt::print("Optimized IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); } @@ -81,7 +80,7 @@ void PrintA64Instruction(u32 instruction) { fmt::print("should_continue: {}\n\n", should_continue); fmt::print("IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); - Optimization::Optimize(ir_block, conf, {}); + Optimization::Optimize(ir_block, A64::UserConfig{}, {}); fmt::print("Optimized IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); } @@ -99,7 +98,7 @@ void PrintThumbInstruction(u32 instruction) { fmt::print("should_continue: {}\n\n", should_continue); fmt::print("IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); - Optimization::Optimize(ir_block, conf, {}); + Optimization::Optimize(ir_block, A32::UserConfig{}, {}); fmt::print("Optimized IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); } From c77ad128b9b4d03f45826d5e5ef32c1328779276 Mon Sep 17 00:00:00 2001 From: crueter Date: Sat, 27 Sep 2025 22:40:08 +0200 Subject: [PATCH 4/7] [cmake] whole-program LTO, prefer lld on clang (#2581) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2581 --- CMakeLists.txt | 42 ++++++++++++++++++++++---------- src/android/app/build.gradle.kts | 4 +-- src/core/CMakeLists.txt | 4 --- src/video_core/CMakeLists.txt | 4 --- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 994bc184fa..ef3c0bef6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,7 +147,11 @@ if (MSVC OR ANDROID) set(EXT_DEFAULT ON) endif() -CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ${EXT_DEFAULT} "ENABLE_SDL2;NOT MSVC" OFF) +if (ENABLE_SDL2) + # TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system + CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF) + option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") +endif() cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF) @@ -185,8 +189,6 @@ option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ${EXT_DEFAULT}) # TODO(crueter): CI this? option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) -# TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system -CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}" "ENABLE_SDL2" OFF) CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) @@ -197,6 +199,14 @@ CMAKE_DEPENDENT_OPTION(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) +if(YUZU_ENABLE_LTO) + include(CheckIPOSupported) + check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) + if(NOT COMPILER_SUPPORTS_LTO) + message(FATAL_ERROR "Your compiler does not support interprocedural optimization (IPO). Re-run CMake with -DYUZU_ENABLE_LTO=OFF.") + endif() + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) +endif() option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" ON) @@ -884,19 +894,25 @@ if (MSVC AND CXX_CLANG) link_libraries(llvm-mingw-runtime) endif() -if (YUZU_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # We will assume that if the compiler is GCC, it will attempt to use ld.bfd by default. - # Try to pick a faster linker. +if (YUZU_USE_FASTER_LD) + # clang should always use lld find_program(LLD lld) - find_program(MOLD mold) - if (MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") - message(NOTICE "Selecting mold as linker") - add_link_options("-fuse-ld=mold") - elseif (LLD) - message(NOTICE "Selecting lld as linker") - add_link_options("-fuse-ld=lld") + if (LLD) + set(LINKER lld) endif() + + # GNU appears to work better with mold + # TODO: mold has been slow lately, see if better options exist (search for gold?) + if (CXX_GCC) + find_program(MOLD mold) + if (MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") + set(LINKER mold) + endif() + endif() + + message(NOTICE "Selecting ${LINKER} as linker") + add_link_options("-fuse-ld=${LINKER}") endif() # Set runtime library to MD/MDd for all configurations diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index c76b5e7162..d3a05cf3e2 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -175,12 +175,10 @@ android { "-DYUZU_USE_CPM=ON", "-DCPMUTIL_FORCE_BUNDLED=ON", "-DYUZU_USE_BUNDLED_FFMPEG=ON", - "-DYUZU_ENABLE_LTO=ON", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-DBUILD_TESTING=OFF", "-DYUZU_TESTS=OFF", - "-DDYNARMIC_TESTS=OFF", - "-DDYNARMIC_ENABLE_LTO=ON" + "-DDYNARMIC_TESTS=OFF" ) abiFilters("arm64-v8a") diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 11c217fce6..62dab070e3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1274,8 +1274,4 @@ if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(core PRIVATE precompiled_headers.h) endif() -if (YUZU_ENABLE_LTO) - set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif() - create_target_directory_groups(core) diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 642494016e..27c8ed9c1d 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -399,10 +399,6 @@ if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(video_core PRIVATE precompiled_headers.h) endif() -if (YUZU_ENABLE_LTO) - set_property(TARGET video_core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif() - if (ANDROID AND ARCHITECTURE_arm64) target_link_libraries(video_core PRIVATE adrenotools) endif() From 02016697d6c63a976cf551b8c9d2cf11fea2fe6d Mon Sep 17 00:00:00 2001 From: nyx Date: Sat, 27 Sep 2025 22:40:18 +0200 Subject: [PATCH 5/7] [cmake, macos] Suppress warnings for unused private members (#2583) Co-authored-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2583 Reviewed-by: Lizzie Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: nyx Co-committed-by: nyx --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 184b049d06..88470c4c42 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -141,7 +141,7 @@ else() -Wno-missing-field-initializers ) - if (CXX_CLANG OR CXX_ICC) # Clang or AppleClang + if (CXX_CLANG OR CXX_ICC OR CXX_APPLE) # Clang, AppleClang, or Intel C++ if (NOT MSVC) add_compile_options( -Werror=shadow-uncaptured-local From 3e57a2cb64f4757e73a2229ecd9719337dd58d97 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 24 Sep 2025 17:43:23 +0000 Subject: [PATCH 6/7] [vk, ogl/IR, dynarmic/IR] friendlier IR identity pointer chasing, inline AA passes Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/ir/opt_passes.cpp | 34 +++++------ .../ir_opt/identity_removal_pass.cpp | 29 +++++---- .../renderer_opengl/present/layer.cpp | 19 +++--- .../renderer_opengl/present/layer.h | 14 ++--- .../renderer_vulkan/present/anti_alias_pass.h | 6 -- .../renderer_vulkan/present/filters.cpp | 39 +++++------- .../renderer_vulkan/present/fsr.cpp | 59 +++++++------------ .../renderer_vulkan/present/layer.cpp | 28 +++++---- .../renderer_vulkan/present/layer.h | 13 ++-- 9 files changed, 106 insertions(+), 135 deletions(-) diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index 844e29023c..18323936d9 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -1226,32 +1226,28 @@ static void DeadCodeElimination(IR::Block& block) { } static void IdentityRemovalPass(IR::Block& block) { - boost::container::small_vector to_invalidate; - - auto iter = block.begin(); - while (iter != block.end()) { - IR::Inst& inst = *iter; - - const size_t num_args = inst.NumArgs(); - for (size_t i = 0; i < num_args; i++) { - while (true) { - IR::Value arg = inst.GetArg(i); - if (!arg.IsIdentity()) - break; - inst.SetArg(i, arg.GetInst()->GetArg(0)); + boost::container::small_vector to_invalidate; + for (auto it = block.begin(); it != block.end();) { + const size_t num_args = it->NumArgs(); + for (size_t i = 0; i < num_args; ++i) { + IR::Value arg = it->GetArg(i); + if (arg.IsIdentity()) { + do { + arg = arg.GetInst()->GetArg(0); + } while (arg.IsIdentity()); + it->SetArg(i, arg); } } - if (inst.GetOpcode() == IR::Opcode::Identity || inst.GetOpcode() == IR::Opcode::Void) { - iter = block.Instructions().erase(inst); - to_invalidate.push_back(&inst); + if (it->GetOpcode() == IR::Opcode::Identity || it->GetOpcode() == IR::Opcode::Void) { + to_invalidate.push_back(&*it); + it = block.Instructions().erase(it); } else { - ++iter; + ++it; } } - for (IR::Inst* inst : to_invalidate) { + for (IR::Inst* const inst : to_invalidate) inst->Invalidate(); - } } static void NamingPass(IR::Block& block) { diff --git a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp index 951534bbf2..18e3553010 100644 --- a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp +++ b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/value.h" @@ -10,28 +11,30 @@ namespace Shader::Optimization { void IdentityRemovalPass(IR::Program& program) { - std::vector to_invalidate; + boost::container::small_vector to_invalidate; for (IR::Block* const block : program.blocks) { - for (auto inst = block->begin(); inst != block->end();) { - const size_t num_args{inst->NumArgs()}; + for (auto it = block->begin(); it != block->end();) { + const size_t num_args{it->NumArgs()}; for (size_t i = 0; i < num_args; ++i) { - IR::Value arg; - while ((arg = inst->Arg(i)).IsIdentity()) { - inst->SetArg(i, arg.Inst()->Arg(0)); + IR::Value arg = it->Arg(i); + if (arg.IsIdentity()) { + do { // Pointer chasing (3-derefs) + arg = arg.Inst()->Arg(0); + } while (arg.IsIdentity()); + it->SetArg(i, arg); } } - if (inst->GetOpcode() == IR::Opcode::Identity || - inst->GetOpcode() == IR::Opcode::Void) { - to_invalidate.push_back(&*inst); - inst = block->Instructions().erase(inst); + + if (it->GetOpcode() == IR::Opcode::Identity || it->GetOpcode() == IR::Opcode::Void) { + to_invalidate.push_back(&*it); + it = block->Instructions().erase(it); } else { - ++inst; + ++it; } } } - for (IR::Inst* const inst : to_invalidate) { + for (IR::Inst* const inst : to_invalidate) inst->Invalidate(); - } } } // namespace Shader::Optimization diff --git a/src/video_core/renderer_opengl/present/layer.cpp b/src/video_core/renderer_opengl/present/layer.cpp index 6c7092d229..6ce4ffa1ff 100644 --- a/src/video_core/renderer_opengl/present/layer.cpp +++ b/src/video_core/renderer_opengl/present/layer.cpp @@ -54,12 +54,12 @@ GLuint Layer::ConfigureDraw(std::array& out_matrix, switch (anti_aliasing) { case Settings::AntiAliasing::Fxaa: CreateFXAA(); - texture = fxaa->Draw(program_manager, info.display_texture); + texture = std::get(anti_alias).Draw(program_manager, info.display_texture); break; case Settings::AntiAliasing::Smaa: default: CreateSMAA(); - texture = smaa->Draw(program_manager, info.display_texture); + texture = std::get(anti_alias).Draw(program_manager, info.display_texture); break; } } @@ -68,7 +68,7 @@ GLuint Layer::ConfigureDraw(std::array& out_matrix, if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { if (!fsr || fsr->NeedsRecreation(layout.screen)) { - fsr = std::make_unique(layout.screen.GetWidth(), layout.screen.GetHeight()); + fsr.emplace(layout.screen.GetWidth(), layout.screen.GetHeight()); } texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop); @@ -199,23 +199,20 @@ void Layer::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuf glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format, framebuffer_texture.width, framebuffer_texture.height); - fxaa.reset(); - smaa.reset(); + anti_alias.emplace(); } void Layer::CreateFXAA() { - smaa.reset(); - if (!fxaa) { - fxaa = std::make_unique( + if (!std::holds_alternative(anti_alias)) { + anti_alias.emplace( Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); } } void Layer::CreateSMAA() { - fxaa.reset(); - if (!smaa) { - smaa = std::make_unique( + if (!std::holds_alternative(anti_alias)) { + anti_alias.emplace( Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); } diff --git a/src/video_core/renderer_opengl/present/layer.h b/src/video_core/renderer_opengl/present/layer.h index 5b15b730fc..a4ebed963c 100644 --- a/src/video_core/renderer_opengl/present/layer.h +++ b/src/video_core/renderer_opengl/present/layer.h @@ -3,11 +3,15 @@ #pragma once -#include +#include +#include #include #include "video_core/host1x/gpu_device_memory_manager.h" #include "video_core/renderer_opengl/gl_resource_manager.h" +#include "video_core/renderer_opengl/present/smaa.h" +#include "video_core/renderer_opengl/present/fxaa.h" +#include "video_core/renderer_opengl/present/fsr.h" namespace Layout { struct FramebufferLayout; @@ -26,11 +30,8 @@ struct FramebufferConfig; namespace OpenGL { struct FramebufferTextureInfo; -class FSR; -class FXAA; class ProgramManager; class RasterizerOpenGL; -class SMAA; /// Structure used for storing information about the textures for the Switch screen struct TextureInfo { @@ -76,9 +77,8 @@ private: /// Display information for Switch screen TextureInfo framebuffer_texture; - std::unique_ptr fsr; - std::unique_ptr fxaa; - std::unique_ptr smaa; + std::optional fsr; + std::variant anti_alias; }; } // namespace OpenGL diff --git a/src/video_core/renderer_vulkan/present/anti_alias_pass.h b/src/video_core/renderer_vulkan/present/anti_alias_pass.h index 1f20fbd7f0..db7bdacd1d 100644 --- a/src/video_core/renderer_vulkan/present/anti_alias_pass.h +++ b/src/video_core/renderer_vulkan/present/anti_alias_pass.h @@ -16,10 +16,4 @@ public: VkImageView* inout_image_view) = 0; }; -class NoAA final : public AntiAliasPass { -public: - void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, - VkImageView* inout_image_view) override {} -}; - } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/filters.cpp b/src/video_core/renderer_vulkan/present/filters.cpp index e0f2b26f84..381031fe6e 100644 --- a/src/video_core/renderer_vulkan/present/filters.cpp +++ b/src/video_core/renderer_vulkan/present/filters.cpp @@ -24,61 +24,52 @@ namespace Vulkan { -namespace { - -vk::ShaderModule SelectScaleForceShader(const Device& device) { - if (device.IsFloat16Supported()) { - return BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FP16_FRAG_SPV); - } else { - return BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FP32_FRAG_SPV); - } -} - -} // Anonymous namespace - std::unique_ptr MakeNearestNeighbor(const Device& device, VkFormat frame_format) { - return std::make_unique(device, frame_format, - CreateNearestNeighborSampler(device), - BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); + return std::make_unique(device, frame_format, CreateNearestNeighborSampler(device), + BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); } std::unique_ptr MakeBilinear(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); + BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); } std::unique_ptr MakeSpline1(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_SPLINE1_FRAG_SPV)); + BuildShader(device, PRESENT_SPLINE1_FRAG_SPV)); } std::unique_ptr MakeBicubic(const Device& device, VkFormat frame_format) { // No need for handrolled shader -- if the VK impl can do it for us ;) if (device.IsExtFilterCubicSupported()) return std::make_unique(device, frame_format, CreateCubicSampler(device), - BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); + BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_BICUBIC_FRAG_SPV)); + BuildShader(device, PRESENT_BICUBIC_FRAG_SPV)); } std::unique_ptr MakeGaussian(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV)); + BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV)); } std::unique_ptr MakeLanczos(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_LANCZOS_FRAG_SPV)); + BuildShader(device, PRESENT_LANCZOS_FRAG_SPV)); } std::unique_ptr MakeScaleForce(const Device& device, VkFormat frame_format) { - return std::make_unique(device, frame_format, CreateBilinearSampler(device), - SelectScaleForceShader(device)); + auto const select_fn = [&]() { + return device.IsFloat16Supported() + ? BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FP16_FRAG_SPV) + : BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FP32_FRAG_SPV); + }; + return std::make_unique(device, frame_format, CreateBilinearSampler(device), select_fn()); } std::unique_ptr MakeArea(const Device& device, VkFormat frame_format) { return std::make_unique(device, frame_format, CreateBilinearSampler(device), - BuildShader(device, PRESENT_AREA_FRAG_SPV)); + BuildShader(device, PRESENT_AREA_FRAG_SPV)); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/fsr.cpp b/src/video_core/renderer_vulkan/present/fsr.cpp index 3f708be704..b2d35cbe97 100644 --- a/src/video_core/renderer_vulkan/present/fsr.cpp +++ b/src/video_core/renderer_vulkan/present/fsr.cpp @@ -41,25 +41,18 @@ FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_c void FSR::CreateImages() { 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.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); } } void FSR::CreateRenderPasses() { m_renderpass = CreateWrappedRenderPass(m_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(m_device, m_renderpass, images.image_views[Easu], m_extent); + images.framebuffers[Rcas] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Rcas], m_extent); } } @@ -87,16 +80,13 @@ void FSR::CreateDescriptorPool() { } void FSR::CreateDescriptorSetLayout() { - m_descriptor_set_layout = - CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); + m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } void FSR::CreateDescriptorSets() { std::vector layouts(MaxFsrStage, *m_descriptor_set_layout); - - for (auto& images : m_dynamic_images) { + for (auto& images : m_dynamic_images) images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); - } } void FSR::CreatePipelineLayouts() { @@ -128,31 +118,24 @@ void FSR::CreatePipelines() { void FSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; - std::vector updates; - image_infos.reserve(2); - - updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, - images.descriptor_sets[Easu], 0)); - updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Easu], - images.descriptor_sets[Rcas], 0)); - + std::vector 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) + }; m_device.GetLogical().UpdateDescriptorSets(updates, {}); } void FSR::UploadImages(Scheduler& scheduler) { - if (m_images_ready) { - return; + if (!m_images_ready) { + m_images_ready = true; + scheduler.Record([&](vk::CommandBuffer cmdbuf) { + for (auto& image : m_dynamic_images) { + ClearColorImage(cmdbuf, *image.images[Easu]); + ClearColorImage(cmdbuf, *image.images[Rcas]); + } + }); + scheduler.Finish(); } - - scheduler.Record([&](vk::CommandBuffer cmdbuf) { - for (auto& image : m_dynamic_images) { - ClearColorImage(cmdbuf, *image.images[Easu]); - ClearColorImage(cmdbuf, *image.images[Rcas]); - } - }); - scheduler.Finish(); - - m_images_ready = true; } VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index fa7c457573..9946335fa3 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -4,7 +4,12 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include "video_core/present.h" +#include "video_core/renderer_vulkan/present/anti_alias_pass.h" +/* X11 defines */ +#undef Success +#undef BadValue #include "video_core/renderer_vulkan/vk_rasterizer.h" #include "common/settings.h" @@ -58,7 +63,7 @@ Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Schedule CreateDescriptorPool(); CreateDescriptorSets(layout); if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { - CreateFSR(output_size); + fsr.emplace(device, memory_allocator, image_count, output_size); } } @@ -97,7 +102,11 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, VkImageView source_image_view = texture_info ? texture_info->image_view : *raw_image_views[image_index]; - anti_alias->Draw(scheduler, image_index, &source_image, &source_image_view); + if (std::holds_alternative(anti_alias)) { + std::get(anti_alias).Draw(scheduler, image_index, &source_image, &source_image_view); + } else if (std::holds_alternative(anti_alias)) { + std::get(anti_alias).Draw(scheduler, image_index, &source_image, &source_image_view); + } auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); const VkExtent2D render_extent{ @@ -156,10 +165,6 @@ void Layer::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { } } -void Layer::CreateFSR(VkExtent2D output_size) { - fsr = std::make_unique(device, memory_allocator, image_count, output_size); -} - void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { if (framebuffer.width == raw_width && framebuffer.height == raw_height && framebuffer.pixel_format == pixel_format && !raw_images.empty()) { @@ -169,7 +174,7 @@ void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { raw_width = framebuffer.width; raw_height = framebuffer.height; pixel_format = framebuffer.pixel_format; - anti_alias.reset(); + anti_alias.emplace(); ReleaseRawImages(); CreateStagingBuffer(framebuffer); @@ -177,9 +182,8 @@ void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { } void Layer::SetAntiAliasPass() { - if (anti_alias && anti_alias_setting == filters.get_anti_aliasing()) { + if (!std::holds_alternative(anti_alias) && anti_alias_setting == filters.get_anti_aliasing()) return; - } anti_alias_setting = filters.get_anti_aliasing(); @@ -190,13 +194,13 @@ void Layer::SetAntiAliasPass() { switch (anti_alias_setting) { case Settings::AntiAliasing::Fxaa: - anti_alias = std::make_unique(device, memory_allocator, image_count, render_area); + anti_alias.emplace(device, memory_allocator, image_count, render_area); break; case Settings::AntiAliasing::Smaa: - anti_alias = std::make_unique(device, memory_allocator, image_count, render_area); + anti_alias.emplace(device, memory_allocator, image_count, render_area); break; default: - anti_alias = std::make_unique(); + anti_alias.emplace(); break; } } diff --git a/src/video_core/renderer_vulkan/present/layer.h b/src/video_core/renderer_vulkan/present/layer.h index f5effdcd7f..6b8fed60ec 100644 --- a/src/video_core/renderer_vulkan/present/layer.h +++ b/src/video_core/renderer_vulkan/present/layer.h @@ -3,9 +3,15 @@ #pragma once +#include +#include + #include "common/math_util.h" #include "video_core/host1x/gpu_device_memory_manager.h" #include "video_core/vulkan_common/vulkan_wrapper.h" +#include "video_core/renderer_vulkan/present/fsr.h" +#include "video_core/renderer_vulkan/present/fxaa.h" +#include "video_core/renderer_vulkan/present/smaa.h" namespace Layout { struct FramebufferLayout; @@ -29,7 +35,6 @@ namespace Vulkan { class AntiAliasPass; class Device; -class FSR; class MemoryAllocator; struct PresentPushConstants; class RasterizerVulkan; @@ -54,7 +59,6 @@ private: void CreateDescriptorSets(VkDescriptorSetLayout layout); void CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer); void CreateRawImages(const Tegra::FramebufferConfig& framebuffer); - void CreateFSR(VkExtent2D output_size); void RefreshResources(const Tegra::FramebufferConfig& framebuffer); void SetAntiAliasPass(); @@ -87,9 +91,8 @@ private: Service::android::PixelFormat pixel_format{}; Settings::AntiAliasing anti_alias_setting{}; - std::unique_ptr anti_alias{}; - - std::unique_ptr fsr{}; + std::variant anti_alias{}; + std::optional fsr{}; std::vector resource_ticks{}; }; From a60cd28b688652b4fe240cfbb8dae3c00686f604 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 24 Sep 2025 17:47:12 +0000 Subject: [PATCH 7/7] Fix license Signed-off-by: lizzie --- src/shader_recompiler/ir_opt/identity_removal_pass.cpp | 3 +++ src/video_core/renderer_opengl/present/layer.cpp | 3 +++ src/video_core/renderer_opengl/present/layer.h | 3 +++ src/video_core/renderer_vulkan/present/anti_alias_pass.h | 3 +++ src/video_core/renderer_vulkan/present/fsr.cpp | 3 +++ src/video_core/renderer_vulkan/present/layer.h | 3 +++ 6 files changed, 18 insertions(+) diff --git a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp index 18e3553010..68f8a9ec44 100644 --- a/src/shader_recompiler/ir_opt/identity_removal_pass.cpp +++ b/src/shader_recompiler/ir_opt/identity_removal_pass.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_opengl/present/layer.cpp b/src/video_core/renderer_opengl/present/layer.cpp index 6ce4ffa1ff..f18600e692 100644 --- a/src/video_core/renderer_opengl/present/layer.cpp +++ b/src/video_core/renderer_opengl/present/layer.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_opengl/present/layer.h b/src/video_core/renderer_opengl/present/layer.h index a4ebed963c..e09fd6f696 100644 --- a/src/video_core/renderer_opengl/present/layer.h +++ b/src/video_core/renderer_opengl/present/layer.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_vulkan/present/anti_alias_pass.h b/src/video_core/renderer_vulkan/present/anti_alias_pass.h index db7bdacd1d..b7d3e2de15 100644 --- a/src/video_core/renderer_vulkan/present/anti_alias_pass.h +++ b/src/video_core/renderer_vulkan/present/anti_alias_pass.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_vulkan/present/fsr.cpp b/src/video_core/renderer_vulkan/present/fsr.cpp index b2d35cbe97..24fc61e813 100644 --- a/src/video_core/renderer_vulkan/present/fsr.cpp +++ b/src/video_core/renderer_vulkan/present/fsr.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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 diff --git a/src/video_core/renderer_vulkan/present/layer.h b/src/video_core/renderer_vulkan/present/layer.h index 6b8fed60ec..062b7792c4 100644 --- a/src/video_core/renderer_vulkan/present/layer.h +++ b/src/video_core/renderer_vulkan/present/layer.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 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