Compare commits

..

3 Commits

Author SHA1 Message Date
Caio Oliveira
e19b42de58 [hle] Update to prevent Shadow-ing a global declaration
Signed-off-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
2025-12-26 06:45:12 +01:00
lizzie
fe4caef919 Fix license
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-12-26 06:45:12 +01:00
lizzie
bdc7af24bd [vk, ogl/IR, dynarmic/IR] friendlier IR identity pointer chasing, inline AA passes
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-12-26 06:45:12 +01:00
16 changed files with 167 additions and 233 deletions

View File

@@ -22,15 +22,6 @@ Or use Qt Creator (Create Project -> Import Project -> Git Clone).
Android has a completely different build process than other platforms. See its [dedicated page](build/Android.md).
## Cross-compile ARM64
A painless guide for cross compilation (or to test NCE) from a x86_64 system without polluting your main.
- Install QEMU: `sudo pkg install qemu`
- Download Debian 13: `wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.0.0-arm64-netinst.iso`
- Create a system disk: `qemu-img create -f qcow2 debian-13-arm64-ci.qcow2 30G`
- Run the VM: `qemu-system-aarch64 -M virt -m 2G -cpu max -bios /usr/local/share/qemu/edk2-aarch64-code.fd -drive if=none,file=debian-13.0.0-arm64-netinst.iso,format=raw,id=cdrom -device scsi-cd,drive=cdrom -drive if=none,file=debian-13-arm64-ci.qcow2,id=hd0,format=qcow2 -device virtio-blk-device,drive=hd0 -device virtio-gpu-pci -device usb-ehci -device usb-kbd -device intel-hda -device hda-output -nic user,model=virtio-net-pci`
## Initial Configuration
If the configure phase fails, see the `Troubleshooting` section below. Usually, as long as you followed the dependencies guide, the defaults *should* successfully configure and build.

View File

@@ -93,11 +93,6 @@ Eden is not currently available as a port on FreeBSD, though it is in the works.
The available OpenSSL port (3.0.17) is out-of-date, and using a bundled static library instead is recommended; to do so, add `-DYUZU_USE_BUNDLED_OPENSSL=ON` to your CMake configure command.
Gamepad/controllers may not work on 15.0, this is due to an outdated SDL not responding well to the new `usbhid(2)` driver. To workaround this simply disable `usbhid(2)` (add the following to `/boot/loader.conf`):
```sh
hw.usb.usbhid.enable="0"
```
## NetBSD
Install `pkgin` if not already `pkg_add pkgin`, see also the general [pkgsrc guide](https://www.netbsd.org/docs/pkgsrc/using.html). For NetBSD 10.1 provide `echo 'PKG_PATH="https://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/x86_64/10.0_2025Q3/All/"' >/etc/pkg_install.conf`. If `pkgin` is taking too much time consider adding the following to `/etc/rc.conf`:
@@ -201,24 +196,14 @@ windeployqt6 --no-compiler-runtime --no-opengl-sw --no-system-dxc-compiler \
find ./*/ -name "*.dll" | while read -r dll; do deps "$dll"; done
```
## RedoxOS
The package install may randomly hang at times, in which case it has to be restarted. ALWAYS do a `sudo pkg update` or the chances of it hanging will be close to 90%. If "multiple" installs fail at once, try installing 1 by 1 the packages.
When CMake invokes certain file syscalls - it may sometimes cause crashes or corruptions on the (kernel?) address space - so reboot the system if there is a "hang" in CMake.
## Windows
### Windows 7, Windows 8 and Windows 8.1
## Windows 8.1 and below
DirectX 12 is not available - simply copy and paste a random DLL and name it `d3d12.dll`.
Install [Qt6 compatibility libraries](github.com/ANightly/qt6windows7) specifically Qt 6.9.5.
### Windows Vista and below
## RedoxOS
No support for Windows Vista (or below) is present at the moment. Check back later.
The package install may randomly hang at times, in which case it has to be restarted. ALWAYS do a `sudo pkg update` or the chances of it hanging will be close to 90%. If "multiple" installs fail at once, try installing 1 by 1 the packages.
### Windows on ARM
If you're using Snapdragon X or 8CX, use the [the Vulkan translation layer](https://apps.microsoft.com/detail/9nqpsl29bfff?hl=en-us&gl=USE) only if the stock drivers do not work. And of course always keep your system up-to-date.
When CMake invokes certain file syscalls - it may sometimes cause crashes or corruptions on the (kernel?) address space - so reboot the system if there is a "hang" in CMake.

View File

@@ -10,13 +10,7 @@ Simply put, types/classes are named as `PascalCase`, same for methods and functi
Except for Qt MOC where `functionName` is preferred.
Template typenames prefer short names like `T`, `I`, `U`, if a longer name is required either `Iterator` or `perform_action` are fine as well. Do not use names like `SS` as systems like solaris define it for registers, in general do not use any of the following for short names:
- `SS`, `DS`, `GS`, `FS`: Segment registers, defined by Solaris `<ucontext.h>`
- `EAX`, `EBX`, `ECX`, `EDX`, `ESI`, `EDI`, `ESP`, `EBP`, `EIP`: Registers, defined by Solaris.
- `X`: Defined by some utility headers, avoid.
- `_`: Defined by gettext, avoid.
- `N`, `M`, `S`: Preferably don't use this for types, use it for numeric constants.
- `TR`: Used by some weird `<ucontext.h>` whom define the Task Register as a logical register to provide to the user... (Need to remember which OS in specific).
Template typenames prefer short names like `T`, `I`, `U`, if a longer name is required either `Iterator` or `perform_action` are fine as well.
Macros must always be in `SCREAMING_CASE`. Do not use short letter macros as systems like Solaris will conflict with them; a good rule of thumb is >5 characters per macro - i.e `THIS_MACRO_IS_GOOD`, `AND_ALSO_THIS_ONE`.
@@ -24,45 +18,25 @@ Try not using hungarian notation, if you're able.
## Formatting
Formatting is extremelly lax, the general rule of thumb is: Don't add new lines just to increase line count. The less lines we have to look at, the better. This means also packing densely your code while not making it a clusterfuck. Strike a balance of "this is a short and comprehensible piece of code" and "my eyes are actually happy to see this!". Don't just drop the entire thing in a single line and call it "dense code", that's just spaghetti posing as code. In general, be mindful of what other devs need to look at.
Do not put if/while/etc braces after lines:
```c++
// no dont do this
// this is more lines of code for no good reason (why braces need their separate lines?)
// and those take space in someone's screen, cumulatively
if (thing)
{ //<--
{
some(); // ...
} //<-- 2 lines of code for basically "opening" and "closing" an statment
}
// do this
if (thing) { //<-- [...] and with your brain you can deduce it's this piece of code
// that's being closed
if (thing) {
some(); // ...
} //<-- only one line, and it's clearer since you know its closing something [...]
}
// or this, albeit the extra line isn't needed (at your discretion of course)
// or this
if (thing)
some(); // ...
// this is also ok, keeps things in one line and makes it extremely clear
// this is also ok
if (thing) some();
// NOT ok, don't be "clever" and use the comma operator to stash a bunch of statments
// in a single line, doing this will definitely ruin someone's day - just do the thing below
// vvv
if (thing) some(), thing(), a2(a1(), y1(), j1()), do_complex_shit(wa(), wo(), ploo());
// ... and in general don't use the comma operator for "multiple statments", EXCEPT if you think
// that it makes the code more readable (the situation may be rare however)
// Wow so much clearer! Now I can actually see what each statment is meant to do!
if (thing) {
some();
thing();
a2(a1(), y1(), j1());
do_complex_shit(wa(), wo(), ploo());
}
```
Brace rules are lax, if you can get the point across, do it:
@@ -103,21 +77,3 @@ if (device_name.empty()) {
SDL_AudioSpec obtained;
device = SDL_OpenAudioDevice(device_name.empty() ? nullptr : device_name.c_str(), capture, &spec, &obtained, false);
```
A note about operators: Use them sparingly, yes, the language is lax on them, but some usages can be... tripping to say the least.
```c++
a, b, c; //<-- NOT OK multiple statments with comma operator is definitely a recipe for disaster
return c ? a : b; //<-- OK ternaries at end of return statments are clear and fine
return a, b; //<-- NOT OK return will take value of `b` but also evaluate `a`, just use a separate statment
void f(int a[]) //<-- OK? if you intend to use the pointer as an array, otherwise just mark it as *
```
And about templates, use them sparingly, don't just do meta-templating for the sake of it, do it when you actually need it. This isn't a competition to see who can make the most complicated and robust meta-templating system. Just use what works, and preferably stick to the standard libary instead of reinventing the wheel. Additionally:
```c++
// NOT OK This will create (T * N * C * P) versions of the same function. DO. NOT. DO. THIS.
template<typename T, size_t N, size_t C, size_t P> inline void what() const noexcept;
// OK use parameters like a normal person, don't be afraid to use them :)
template<typename T> inline void what(size_t n, size_t c, size_t p) const noexcept;
```

10
docs/CrossCompile.md Normal file
View File

@@ -0,0 +1,10 @@
# Cross Compile
## ARM64
A painless guide for cross compilation (or to test NCE) from a x86_64 system without polluting your main.
- Install QEMU: `sudo pkg install qemu`
- Download Debian 13: `wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.0.0-arm64-netinst.iso`
- Create a system disk: `qemu-img create -f qcow2 debian-13-arm64-ci.qcow2 30G`
- Run the VM: `qemu-system-aarch64 -M virt -m 2G -cpu max -bios /usr/local/share/qemu/edk2-aarch64-code.fd -drive if=none,file=debian-13.0.0-arm64-netinst.iso,format=raw,id=cdrom -device scsi-cd,drive=cdrom -drive if=none,file=debian-13-arm64-ci.qcow2,id=hd0,format=qcow2 -device virtio-blk-device,drive=hd0 -device virtio-gpu-pci -device usb-ehci -device usb-kbd -device intel-hda -device hda-output -nic user,model=virtio-net-pci`

View File

@@ -294,22 +294,22 @@ sudo pkg install qt6 boost glslang libzip library/lz4 libusb-1 nlohmann-json ope
* Open the `MSYS2 MinGW 64-bit` shell (`mingw64.exe`)
* Download and install all dependencies:
```sh
```
BASE="git make autoconf libtool automake-wrapper jq patch"
MINGW="qt6-base qt6-tools qt6-translations qt6-svg cmake toolchain clang python-pip openssl vulkan-memory-allocator vulkan-devel glslang boost fmt lz4 nlohmann-json zlib zstd enet opus mbedtls libusb unordered_dense openssl SDL2"
# Either x86_64 or clang-aarch64 (Windows on ARM)
MINGW="qt6-base qt6-tools qt6-translations qt6-svg cmake toolchain clang python-pip openssl vulkan-memory-allocator vulkan-devel glslang boost fmt lz4 nlohmann-json zlib zstd enet opus mbedtls libusb unordered_dense"
packages="$BASE"
for pkg in $MINGW; do
packages="$packages mingw-w64-x86_64-$pkg"
#packages="$packages mingw-w64-clang-aarch64-$pkg"
done
pacman -Syuu --needed --noconfirm $packages
```
* Notes:
- Using `qt6-static` is possible but currently untested.
- Other environments are entirely untested, but should theoretically work provided you install all the necessary packages.
- GCC is proven to work better with the MinGW environment. If you choose to use Clang, you *may* be better off using the clang64 environment.
- ...except on ARM64, we recommend using clang instead of GCC for Windows ARM64.
- Add `qt-creator` to the `MINGW` variable to install Qt Creator. You can then create a Start Menu shortcut to the MinGW Qt Creator by running `powershell "\$s=(New-Object -COM WScript.Shell).CreateShortcut('C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Qt Creator.lnk');\$s.TargetPath='C:\\msys64\\mingw64\\bin\\qtcreator.exe';\$s.Save()"` in Git Bash or MSYS2.
* Add MinGW binaries to the PATH if they aren't already:
* `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc`

View File

@@ -12,7 +12,7 @@
#include "common/common_types.h"
#include "common/expected.h"
// All the constants in this file come from <http://switchbrew.org/index.php?title=Error_codes>
// All the constants in this file come from <https://switchbrew.org/wiki/Error_codes>
/**
* Identifies the module which caused the error. Error codes can be propagated through a call
@@ -43,7 +43,7 @@ enum class ErrorModule : u32 {
NCMContent = 20,
SM = 21,
RO = 22,
GC = 23,
Gc = 23,
SDMMC = 24,
OVLN = 25,
SPL = 26,
@@ -72,7 +72,7 @@ enum class ErrorModule : u32 {
Bluetooth = 113,
VI = 114,
NFP = 115,
Time = 116,
TimeService = 116,
FGM = 117,
OE = 118,
BH1730FVC = 119,

View File

@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -7,18 +10,18 @@
namespace Service::PSC::Time {
constexpr Result ResultPermissionDenied{ErrorModule::Time, 1};
constexpr Result ResultClockMismatch{ErrorModule::Time, 102};
constexpr Result ResultClockUninitialized{ErrorModule::Time, 103};
constexpr Result ResultTimeNotFound{ErrorModule::Time, 200};
constexpr Result ResultOverflow{ErrorModule::Time, 201};
constexpr Result ResultFailed{ErrorModule::Time, 801};
constexpr Result ResultInvalidArgument{ErrorModule::Time, 901};
constexpr Result ResultTimeZoneOutOfRange{ErrorModule::Time, 902};
constexpr Result ResultTimeZoneParseFailed{ErrorModule::Time, 903};
constexpr Result ResultRtcTimeout{ErrorModule::Time, 988};
constexpr Result ResultTimeZoneNotFound{ErrorModule::Time, 989};
constexpr Result ResultNotImplemented{ErrorModule::Time, 990};
constexpr Result ResultAlarmNotRegistered{ErrorModule::Time, 1502};
constexpr Result ResultPermissionDenied{ErrorModule::TimeService, 1};
constexpr Result ResultClockMismatch{ErrorModule::TimeService, 102};
constexpr Result ResultClockUninitialized{ErrorModule::TimeService, 103};
constexpr Result ResultTimeNotFound{ErrorModule::TimeService, 200};
constexpr Result ResultOverflow{ErrorModule::TimeService, 201};
constexpr Result ResultFailed{ErrorModule::TimeService, 801};
constexpr Result ResultInvalidArgument{ErrorModule::TimeService, 901};
constexpr Result ResultTimeZoneOutOfRange{ErrorModule::TimeService, 902};
constexpr Result ResultTimeZoneParseFailed{ErrorModule::TimeService, 903};
constexpr Result ResultRtcTimeout{ErrorModule::TimeService, 988};
constexpr Result ResultTimeZoneNotFound{ErrorModule::TimeService, 989};
constexpr Result ResultNotImplemented{ErrorModule::TimeService, 990};
constexpr Result ResultAlarmNotRegistered{ErrorModule::TimeService, 1502};
} // namespace Service::PSC::Time

View File

@@ -1227,32 +1227,28 @@ static void DeadCodeElimination(IR::Block& block) {
}
static void IdentityRemovalPass(IR::Block& block) {
boost::container::small_vector<IR::Inst*, 128> 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<IR::Inst*, 16> 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) {

View File

@@ -1,7 +1,11 @@
// 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
#include <vector>
#include <boost/container/small_vector.hpp>
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/value.h"
@@ -10,28 +14,30 @@
namespace Shader::Optimization {
void IdentityRemovalPass(IR::Program& program) {
std::vector<IR::Inst*> to_invalidate;
boost::container::small_vector<IR::Inst*, 16> 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

View File

@@ -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
@@ -54,12 +57,12 @@ GLuint Layer::ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix,
switch (anti_aliasing) {
case Settings::AntiAliasing::Fxaa:
CreateFXAA();
texture = fxaa->Draw(program_manager, info.display_texture);
texture = std::get<FXAA>(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<SMAA>(anti_alias).Draw(program_manager, info.display_texture);
break;
}
}
@@ -68,7 +71,7 @@ GLuint Layer::ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix,
if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) {
if (!fsr || fsr->NeedsRecreation(layout.screen)) {
fsr = std::make_unique<FSR>(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 +202,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<std::monostate>();
}
void Layer::CreateFXAA() {
smaa.reset();
if (!fxaa) {
fxaa = std::make_unique<FXAA>(
if (!std::holds_alternative<FXAA>(anti_alias)) {
anti_alias.emplace<FXAA>(
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<SMAA>(
if (!std::holds_alternative<SMAA>(anti_alias)) {
anti_alias.emplace<SMAA>(
Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
}

View File

@@ -1,13 +1,20 @@
// 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
#pragma once
#include <memory>
#include <optional>
#include <variant>
#include <vector>
#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 +33,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 +80,8 @@ private:
/// Display information for Switch screen
TextureInfo framebuffer_texture;
std::unique_ptr<FSR> fsr;
std::unique_ptr<FXAA> fxaa;
std::unique_ptr<SMAA> smaa;
std::optional<FSR> fsr;
std::variant<std::monostate, FXAA, SMAA> anti_alias;
};
} // namespace OpenGL

View File

@@ -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
@@ -16,10 +19,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

View File

@@ -30,32 +30,19 @@
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<WindowAdaptPass> MakeNearestNeighbor(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format,
CreateNearestNeighborSampler(device),
BuildShader(device, VULKAN_PRESENT_FRAG_SPV));
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateNearestNeighborSampler(device),
BuildShader(device, VULKAN_PRESENT_FRAG_SPV));
}
std::unique_ptr<WindowAdaptPass> MakeBilinear(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateBilinearSampler(device),
BuildShader(device, VULKAN_PRESENT_FRAG_SPV));
BuildShader(device, VULKAN_PRESENT_FRAG_SPV));
}
std::unique_ptr<WindowAdaptPass> MakeSpline1(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateBilinearSampler(device),
BuildShader(device, PRESENT_SPLINE1_FRAG_SPV));
BuildShader(device, PRESENT_SPLINE1_FRAG_SPV));
}
std::unique_ptr<WindowAdaptPass> MakeBicubic(const Device& device, VkFormat frame_format, VkCubicFilterWeightsQCOM qcom_weights) {
@@ -84,22 +71,26 @@ std::unique_ptr<WindowAdaptPass> MakeBicubic(const Device& device, VkFormat fram
std::unique_ptr<WindowAdaptPass> MakeGaussian(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateBilinearSampler(device),
BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV));
BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV));
}
std::unique_ptr<WindowAdaptPass> MakeLanczos(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateBilinearSampler(device),
BuildShader(device, PRESENT_LANCZOS_FRAG_SPV));
BuildShader(device, PRESENT_LANCZOS_FRAG_SPV));
}
std::unique_ptr<WindowAdaptPass> MakeScaleForce(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(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<WindowAdaptPass>(device, frame_format, CreateBilinearSampler(device), select_fn());
}
std::unique_ptr<WindowAdaptPass> MakeArea(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateBilinearSampler(device),
BuildShader(device, PRESENT_AREA_FRAG_SPV));
BuildShader(device, PRESENT_AREA_FRAG_SPV));
}
std::unique_ptr<WindowAdaptPass> MakeMmpx(const Device& device, VkFormat frame_format) {

View File

@@ -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
@@ -41,25 +44,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 +83,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<VkDescriptorSetLayout> 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 +121,24 @@ void FSR::CreatePipelines() {
void FSR::UpdateDescriptorSets(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(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<VkWriteDescriptorSet> updates{
CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[Easu], 0),
CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Easu], images.descriptor_sets[Rcas], 0)
};
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,

View File

@@ -4,7 +4,12 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <variant>
#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<FXAA>(anti_alias)) {
std::get<FXAA>(anti_alias).Draw(scheduler, image_index, &source_image, &source_image_view);
} else if (std::holds_alternative<SMAA>(anti_alias)) {
std::get<SMAA>(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<FSR>(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<std::monostate>();
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<std::monostate>(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<FXAA>(device, memory_allocator, image_count, render_area);
anti_alias.emplace<FXAA>(device, memory_allocator, image_count, render_area);
break;
case Settings::AntiAliasing::Smaa:
anti_alias = std::make_unique<SMAA>(device, memory_allocator, image_count, render_area);
anti_alias.emplace<SMAA>(device, memory_allocator, image_count, render_area);
break;
default:
anti_alias = std::make_unique<NoAA>();
anti_alias.emplace<std::monostate>();
break;
}
}

View File

@@ -1,11 +1,20 @@
// 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
#pragma once
#include <optional>
#include <variant>
#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 +38,6 @@ namespace Vulkan {
class AntiAliasPass;
class Device;
class FSR;
class MemoryAllocator;
struct PresentPushConstants;
class RasterizerVulkan;
@@ -54,7 +62,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 +94,8 @@ private:
Service::android::PixelFormat pixel_format{};
Settings::AntiAliasing anti_alias_setting{};
std::unique_ptr<AntiAliasPass> anti_alias{};
std::unique_ptr<FSR> fsr{};
std::variant<std::monostate, FXAA, SMAA> anti_alias{};
std::optional<FSR> fsr{};
std::vector<u64> resource_ticks{};
};