Compare commits
3 Commits
docsupdate
...
liz-coales
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e19b42de58 | ||
|
|
fe4caef919 | ||
|
|
bdc7af24bd |
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
10
docs/CrossCompile.md
Normal 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`
|
||||
10
docs/Deps.md
10
docs/Deps.md
@@ -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`
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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{};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user