1
0
mirror of https://git.suyu.dev/suyu/suyu synced 2025-12-16 08:15:14 -06:00

5 Commits

Author SHA1 Message Date
Crimson-Hawk
8cd1a0a7c8 include torzu in copyright headers 2024-04-27 07:39:13 +08:00
rafaelpro12
f05abd9b02 Merge branch 'dev' into optimize-spirv 2024-04-26 23:36:15 +02:00
Crimson-Hawk
94b72df61e fixed build and correct copyright headers 2024-04-25 21:41:03 +08:00
Crimson-Hawk
93e5d01452 correct submodules 2024-04-25 21:32:04 +08:00
Crimson-Hawk
4b54749954 experimental optimization for spirv 2024-04-25 21:14:30 +08:00
20 changed files with 257 additions and 2220 deletions

10
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: 2014 Citra Emulator Project
# SPDX-FileCopyrightText: 2024 suyu Emulator Project
# SPDX-FileCopyrightText: 2024 Torzu Emulator Project
# SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
# SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
[submodule "enet"]
@@ -69,6 +69,6 @@
[submodule "Vulkan-Utility-Libraries"]
path = externals/Vulkan-Utility-Libraries
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
[submodule "externals/boost-headers"]
path = externals/boost-headers
url = https://github.com/boostorg/headers.git
[submodule "externals/SPIRV-Tools"]
path = externals/SPIRV-Tools
url = https://github.com/KhronosGroup/SPIRV-Tools.git

View File

@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: 2024 suyu Emulator Project
# SPDX-FileCopyrightText: 2024 Torzu Emulator Project
# SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
cmake_minimum_required(VERSION 3.22)
@@ -41,6 +41,8 @@ option(SUYU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(SUYU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
option(SUYU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS "Use SPIRV-Tools from externals" ON)
option(SUYU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
option(SUYU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
@@ -277,8 +279,20 @@ if (ARCHITECTURE_arm64 AND (ANDROID OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
add_definitions(-DHAS_NCE=1)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Configure C++ standard
# ===========================
# boost asio's concept usage doesn't play nicely with some compilers yet.
add_definitions(-DBOOST_ASIO_DISABLE_CONCEPTS)
if (MSVC)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/std:c++20>)
# boost still makes use of deprecated result_of.
add_definitions(-D_HAS_DEPRECATED_RESULT_OF)
else()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
# Output binaries to bin/
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
@@ -287,6 +301,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
# =======================================================================
# Enforce the search mode of non-required packages for better and shorter failure messages
find_package(Boost 1.79.0 REQUIRED context)
find_package(enet 1.3 MODULE)
find_package(fmt 9 REQUIRED)
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
@@ -308,6 +323,11 @@ if (NOT SUYU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
find_package(VulkanUtilityLibraries REQUIRED)
endif()
if (NOT SUYU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SPIRV-Tools REQUIRED SPIRV-Tools)
endif()
if (ENABLE_LIBUSB)
find_package(libusb 1.0.24 MODULE)
endif()
@@ -344,6 +364,11 @@ if (SUYU_TESTS)
find_package(Catch2 3.0.1 REQUIRED)
endif()
# boost:asio has functions that require AcceptEx et al
if (MINGW)
find_library(MSWSOCK_LIBRARY mswsock REQUIRED)
endif()
if(ENABLE_OPENSSL)
find_package(OpenSSL 1.1.1 REQUIRED)
endif()
@@ -670,6 +695,8 @@ function(create_target_directory_groups target_name)
endforeach()
endfunction()
# Prevent boost from linking against libs when building
target_link_libraries(Boost::headers INTERFACE Boost::disable_autolinking)
# Adjustments for MSVC + Ninja
if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
add_compile_options(

View File

@@ -6,5 +6,5 @@ SPDX-License-Identifier: GPL-2.0-or-later
Please check out the
* [Contributors's guide](https://git.suyu.dev/suyu/suyu/wiki/Contributing).
* [Merge request guidelines](https://git.suyu.dev/suyu/suyu/wiki/Typical-Git-Workflow#once-your-pull-request-is-ready-to-be-merged)
* [Contributors's guide](https://gitlab.com/suyu-emu/suyu/-/wikis/Contributing).
* [Merge request guidelines](https://gitlab.com/suyu-emu/suyu/-/wikis/Merge-requests)

View File

@@ -1,25 +0,0 @@
<!--
SPDX-FileCopyrightText: 2024 suyu Emulator Project
SPDX-License-Identifier: GPL-3.0-or-later
-->
# Migrating from yuzu
When coming from yuzu, the migration is as easy as renaming some directories.
## Windows
Use the run dialog to go to `%APPDATA%` or manually go to `C:\Users\{USERNAME}\AppData\Roaming` (you may have to enable hidden files) and simply rename the `yuzu` directories and simply rename those to `suyu`.
## Unix (macOS/Linux)
Similarly, you can simply rename the folders `~/.local/share/yuzu` and `~/.config/yuzu` to `suyu`, either via a file manager or with the following commands:
```sh
$ mv ~/.local/share/yuzu ~/.local/share/suyu
$ mv ~/.config/yuzu ~/.config/suyu
```
There is also `~/.cache/yuzu`, which you can safely delete. Suyu will build a fresh cache in its own directory.
### Linux
Depending on your setup, you may want to substitute those base paths for `$XDG_DATA_HOME` and `$XDG_CONFIG_HOME` respectively.
## Android
TBD

View File

@@ -9,6 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
We're in need of developers. Please join our chat below if you want to contribute!
This repo was based on Yuzu EA 4176 but the code is being rewritten from the ground up for legal and performance reasons.
Support the original suyu developer team [here](https://discord.gg/ajz5hdrZ)
<hr />
@@ -22,7 +23,7 @@ This repo was based on Yuzu EA 4176 but the code is being rewritten from the gro
<h4 align="center"><b>suyu</b> was the continuation of the world's most popular, open-source Nintendo Switch emulator, yuzu, but is now something more.
<br>
It is written in C++ with portability in mind, and we actively provide builds for Windows, Linux, Android and iOS potentially coming soon.
It is written in C++ (C# possibly required soon) with portability in mind, we actively work on builds for Windows, Linux, Android and hopefully IOS, along with a WIP custom OS called suyuOS (https://git.suyu.dev/suyu/suyu-os) .
</h4>
@@ -40,10 +41,6 @@ It is written in C++ with portability in mind, and we actively provide builds fo
## Hardware Requirements
[Click here to see the Hardware Requirements](https://git.suyu.dev/suyu/suyu/wiki/Hardware-Requirements)
## Migrating from yuzu
See [MIGRATION.md](MIGRATION.md).
## Status
We currently have builds over at the [Releases](https://git.suyu.dev/suyu/suyu/releases) page.
@@ -54,10 +51,10 @@ We currently have builds over at the [Releases](https://git.suyu.dev/suyu/suyu/r
This project is completely free and open source, and anyone can contribute to help improve suyu.
Most of the development happens on the Git. For development discussion, please join us in our [Chat](https://chat.suyu.dev) or contact a developer.
Most of the development happens on GitLab. For development discussion, please join us in our [Chat](https://chat.suyu.dev).
If you want to contribute, please take a look at the [Contributor's Guide](https://git.suyu.dev/suyu/suyu/wiki/Contributing) and [Developer Information](https://git.suyu.dev/suyu/suyu/wiki/Developer-Information).
You can also contact any of the developers on the Chat to learn more about the current state of suyu.
You can also contact any of the developers on Discord to learn more about the current state of suyu.
## Downloads
@@ -65,12 +62,13 @@ You can also contact any of the developers on the Chat to learn more about the c
* __Linux__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
* __macOS__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
* __Android__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
###### We currently do not provide builds for iOS, however if you would like, you could try the experimental [Sudachi](https://github.com/emuPlace/Sudachi/releases)/[Folium](https://github.com/jarrodnorwell/Folium/releases).
* __For IOS users, we recommend Sudachi__: [Releases](https://github.com/emuPlace/Sudachi/releases)
If you want daily builds then [Click here](https://git.suyu.dev/suyu/suyu/actions).
If you want daily builds then [Click here](https://git.suyu.dev/suyu/suyu/actions)
If you don't know how to download the daily builds then [Click here](https://git.suyu.dev/suyu/suyu/raw/branch/dev/img/daily-builds.png)
Right now we only have daily builds for Linux and Android.
We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases)<br>If any website or person is claiming to have a build for suyu, take that with a grain of salt.
We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases) If any website or person is claiming to have a build for suyu, take that with a grain of salt.
## Building
@@ -83,7 +81,7 @@ We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases)<br>If a
## Support
If you have any questions, don't hesitate to ask us in our [chat](https://chat.suyu.dev), make an issue or contact a developer. We don't bite!
If you have any questions, don't hesitate to ask us in our [chat](https://chat.suyu.dev). We don't bite!
## License

View File

@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
# SPDX-FileCopyrightText: 2024 suyu Emulator Project
# SPDX-FileCopyrightText: 2024 Torzu Emulator Project
# SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
# SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Dynarmic has cmake_minimum_required(3.12) and we may want to override
@@ -162,8 +162,10 @@ if (SUYU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
add_subdirectory(Vulkan-Utility-Libraries)
endif()
# Boost headers
add_subdirectory(boost-headers)
# SPIRV-Tools
if (YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS)
add_subdirectory(SPIRV-Tools)
endif()
# TZDB (Time Zone Database)
add_subdirectory(nx_tzdb)

1
externals/SPIRV-Tools vendored Submodule

Submodule externals/SPIRV-Tools added at dd4b663e13

Submodule externals/boost-headers deleted from 0456900fad

View File

@@ -1,6 +1,5 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: 2024 suyu Emulator Project
# SPDX-FileCopyrightText: 2024 Torzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
if (DEFINED ENV{AZURECIREPO})
@@ -263,7 +262,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
)
endif()
target_link_libraries(common PUBLIC Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
if (ANDROID)

View File

@@ -1,52 +1,91 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <mutex>
#include "common/assert.h"
#include "common/fiber.h"
#define MINICORO_IMPL
#include "common/minicoro.h"
#include "common/virtual_buffer.h"
#include <boost/context/detail/fcontext.hpp>
namespace Common {
constexpr std::size_t default_stack_size = 512 * 1024;
struct Fiber::FiberImpl {
FiberImpl() {}
FiberImpl() : stack{default_stack_size}, rewind_stack{default_stack_size} {}
VirtualBuffer<u8> stack;
VirtualBuffer<u8> rewind_stack;
std::mutex guard;
bool released{};
bool is_thread_fiber{};
Fiber* next_fiber{};
Fiber** next_fiber_ptr;
std::function<void()> entry_point;
std::function<void()> rewind_point;
std::shared_ptr<Fiber> previous_fiber;
bool is_thread_fiber{};
bool released{};
mco_coro* context;
u8* stack_limit{};
u8* rewind_stack_limit{};
boost::context::detail::fcontext_t context{};
boost::context::detail::fcontext_t rewind_context{};
};
Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {
impl->is_thread_fiber = true;
void Fiber::SetRewindPoint(std::function<void()>&& rewind_func) {
impl->rewind_point = std::move(rewind_func);
}
void Fiber::Start(boost::context::detail::transfer_t& transfer) {
ASSERT(impl->previous_fiber != nullptr);
impl->previous_fiber->impl->context = transfer.fctx;
impl->previous_fiber->impl->guard.unlock();
impl->previous_fiber.reset();
impl->entry_point();
UNREACHABLE();
}
void Fiber::OnRewind([[maybe_unused]] boost::context::detail::transfer_t& transfer) {
ASSERT(impl->context != nullptr);
impl->context = impl->rewind_context;
impl->rewind_context = nullptr;
u8* tmp = impl->stack_limit;
impl->stack_limit = impl->rewind_stack_limit;
impl->rewind_stack_limit = tmp;
impl->rewind_point();
UNREACHABLE();
}
void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) {
auto* fiber = static_cast<Fiber*>(transfer.data);
fiber->Start(transfer);
}
void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) {
auto* fiber = static_cast<Fiber*>(transfer.data);
fiber->OnRewind(transfer);
}
Fiber::Fiber(std::function<void()>&& entry_point_func) : impl{std::make_unique<FiberImpl>()} {
impl->entry_point = std::move(entry_point_func);
auto desc = mco_desc_init(
[](mco_coro* coro) { reinterpret_cast<Fiber*>(coro->user_data)->impl->entry_point(); }, 0);
desc.user_data = this;
mco_result res = mco_create(&impl->context, &desc);
ASSERT(res == MCO_SUCCESS);
impl->stack_limit = impl->stack.data();
impl->rewind_stack_limit = impl->rewind_stack.data();
u8* stack_base = impl->stack_limit + default_stack_size;
impl->context =
boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc);
}
Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
Fiber::~Fiber() {
if (impl->released) {
return;
}
DestroyPre();
if (impl->is_thread_fiber) {
DestroyThreadFiber();
} else {
DestroyWorkFiber();
// Make sure the Fiber is not being used
const bool locked = impl->guard.try_lock();
ASSERT_MSG(locked, "Destroying a fiber that's still running");
if (locked) {
impl->guard.unlock();
}
}
@@ -55,66 +94,42 @@ void Fiber::Exit() {
if (!impl->is_thread_fiber) {
return;
}
DestroyPre();
DestroyThreadFiber();
}
void Fiber::DestroyPre() {
// Make sure the Fiber is not being used
const bool locked = impl->guard.try_lock();
ASSERT_MSG(locked, "Destroying a fiber that's still running");
if (locked) {
impl->guard.unlock();
}
impl->guard.unlock();
impl->released = true;
}
void Fiber::DestroyWorkFiber() {
mco_result res = mco_destroy(impl->context);
ASSERT(res == MCO_SUCCESS);
}
void Fiber::DestroyThreadFiber() {
if (*impl->next_fiber_ptr) {
*impl->next_fiber_ptr = nullptr;
}
void Fiber::Rewind() {
ASSERT(impl->rewind_point);
ASSERT(impl->rewind_context == nullptr);
u8* stack_base = impl->rewind_stack_limit + default_stack_size;
impl->rewind_context =
boost::context::detail::make_fcontext(stack_base, impl->stack.size(), RewindStartFunc);
boost::context::detail::jump_fcontext(impl->rewind_context, this);
}
void Fiber::YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to) {
to.impl->guard.lock();
to.impl->previous_fiber = weak_from.lock();
auto transfer = boost::context::detail::jump_fcontext(to.impl->context, &to);
// "from" might no longer be valid if the thread was killed
if (auto from = weak_from.lock()) {
if (!from->impl->is_thread_fiber) {
// Set next fiber
from->impl->next_fiber = &to;
// Yield from thread
if (!from->impl->released) {
from->impl->guard.unlock();
mco_yield(from->impl->context);
}
} else {
from->impl->guard.lock();
// Keep running next fiber until they've ran out
auto& next_fiber_ptr = from->impl->next_fiber_ptr;
next_fiber_ptr = &from->impl->next_fiber;
*next_fiber_ptr = &to;
for ([[maybe_unused]] unsigned round = 0; *next_fiber_ptr; round++) {
auto next = *next_fiber_ptr;
*next_fiber_ptr = nullptr;
next_fiber_ptr = &next->impl->next_fiber;
// Stop if new thread is thread fiber
if (next->impl->is_thread_fiber)
break;
// Resume new thread
next->impl->guard.lock();
mco_result res = mco_resume(next->impl->context);
ASSERT(res == MCO_SUCCESS);
}
from->impl->guard.unlock();
if (from->impl->previous_fiber == nullptr) {
ASSERT_MSG(false, "previous_fiber is nullptr!");
return;
}
from->impl->previous_fiber->impl->context = transfer.fctx;
from->impl->previous_fiber->impl->guard.unlock();
from->impl->previous_fiber.reset();
}
}
std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
return std::shared_ptr<Fiber>{new Fiber()};
std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
fiber->impl->guard.lock();
fiber->impl->is_thread_fiber = true;
return fiber;
}
} // namespace Common
} // namespace Common

View File

@@ -1,6 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -8,7 +6,9 @@
#include <functional>
#include <memory>
#include "common/minicoro.h"
namespace boost::context::detail {
struct transfer_t;
}
namespace Common {
@@ -38,21 +38,28 @@ public:
Fiber(Fiber&&) = default;
Fiber& operator=(Fiber&&) = default;
/// Yields control from Fiber 'from' to Fiber 'to'
/// Fiber 'from' must be the currently running fiber.
static void YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to);
[[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
void SetRewindPoint(std::function<void()>&& rewind_func);
void Rewind();
/// Only call from main thread's fiber
void Exit();
private:
Fiber();
void DestroyPre();
void DestroyWorkFiber();
void DestroyThreadFiber();
void OnRewind(boost::context::detail::transfer_t& transfer);
void Start(boost::context::detail::transfer_t& transfer);
static void FiberStartFunc(boost::context::detail::transfer_t transfer);
static void RewindStartFunc(boost::context::detail::transfer_t transfer);
struct FiberImpl;
std::unique_ptr<FiberImpl> impl;
};
} // namespace Common
} // namespace Common

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -277,6 +279,8 @@ struct Values {
SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache",
Category::Renderer};
SwitchableSetting<bool> optimize_spirv_output{linkage, false, "optimize_spirv_output",
Category::Renderer};
SwitchableSetting<bool> use_asynchronous_gpu_emulation{
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,

View File

@@ -1,4 +1,6 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
# SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
add_library(shader_recompiler STATIC
@@ -242,7 +244,13 @@ add_library(shader_recompiler STATIC
varying_state.h
)
target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit)
if (SUYU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS)
set(SPIRV_TOOLS_LIBRARY SPIRV-Tools-opt)
else()
set(SPIRV_TOOLS_LIBRARY SPIRV-Tools-opt SPIRV-Tools SPIRV-Tools-link)
endif()
target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit ${SPIRV_TOOLS_LIBRARY})
if (MSVC)
target_compile_options(shader_recompiler PRIVATE

View File

@@ -1,4 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <span>
@@ -6,6 +8,7 @@
#include <type_traits>
#include <utility>
#include <vector>
#include <spirv-tools/optimizer.hpp>
#include "common/settings.h"
#include "shader_recompiler/backend/spirv/emit_spirv.h"
@@ -481,7 +484,7 @@ void PatchPhiNodes(IR::Program& program, EmitContext& ctx) {
} // Anonymous namespace
std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info,
IR::Program& program, Bindings& bindings) {
IR::Program& program, Bindings& bindings, bool optimize) {
EmitContext ctx{profile, runtime_info, program, bindings};
const Id main{DefineMain(ctx, program)};
DefineEntryPoint(program, ctx, main);
@@ -493,7 +496,28 @@ std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_in
SetupCapabilities(profile, program.info, ctx);
SetupTransformFeedbackCapabilities(ctx, main);
PatchPhiNodes(program, ctx);
return ctx.Assemble();
if (!optimize) {
return ctx.Assemble();
} else {
std::vector<u32> spirv = ctx.Assemble();
spvtools::Optimizer spv_opt(SPV_ENV_VULKAN_1_3);
spv_opt.SetMessageConsumer([](spv_message_level_t, const char*, const spv_position_t&,
const char* m) { LOG_ERROR(HW_GPU, "spirv-opt: {}", m); });
spv_opt.RegisterPerformancePasses();
spvtools::OptimizerOptions opt_options;
opt_options.set_run_validator(false);
std::vector<u32> result;
if (!spv_opt.Run(spirv.data(), spirv.size(), &result, opt_options)) {
LOG_ERROR(HW_GPU,
"Failed to optimize SPIRV shader output, continuing without optimization");
result = std::move(spirv);
}
return result;
}
}
Id EmitPhi(EmitContext& ctx, IR::Inst* inst) {
@@ -556,4 +580,4 @@ void EmitGetInBoundsFromOp(EmitContext&) {
throw LogicError("Unreachable instruction");
}
} // namespace Shader::Backend::SPIRV
} // namespace Shader::Backend::SPIRV

View File

@@ -1,4 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -31,11 +33,12 @@ constexpr u32 RESCALING_LAYOUT_DOWN_FACTOR_OFFSET = offsetof(RescalingLayout, do
constexpr u32 RENDERAREA_LAYOUT_OFFSET = offsetof(RenderAreaLayout, render_area);
[[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info,
IR::Program& program, Bindings& bindings);
IR::Program& program, Bindings& bindingss, bool optimize);
[[nodiscard]] inline std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program) {
[[nodiscard]] inline std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program,
bool optimize) {
Bindings binding;
return EmitSPIRV(profile, {}, program, binding);
return EmitSPIRV(profile, {}, program, binding, optimize);
}
} // namespace Shader::Backend::SPIRV

View File

@@ -1,4 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "suyu/configuration/shared_translation.h"
@@ -143,6 +145,10 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
tr("Allows saving shaders to storage for faster loading on following game "
"boots.\nDisabling "
"it is only intended for debugging."));
INSERT(Settings, optimize_spirv_output, tr("Optimize SPIRV output shader"),
tr("Runs an additional optimization pass over generated SPIRV shaders.\n"
"Will increase time required for shader compilation.\nMay slightly improve "
"performance.\nThis feature is experimental."));
INSERT(
Settings, use_asynchronous_gpu_emulation, tr("Use asynchronous GPU emulation"),
tr("Uses an extra CPU thread for rendering.\nThis option should always remain enabled."));

View File

@@ -1,5 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <atomic>
@@ -272,4 +271,43 @@ TEST_CASE("Fibers::StartRace", "[common]") {
REQUIRE(test_control.value3 == 1);
}
class TestControl4;
class TestControl4 {
public:
TestControl4() {
fiber1 = std::make_shared<Fiber>([this] { DoWork(); });
goal_reached = false;
rewinded = false;
}
void Execute() {
thread_fiber = Fiber::ThreadToFiber();
Fiber::YieldTo(thread_fiber, *fiber1);
thread_fiber->Exit();
}
void DoWork() {
fiber1->SetRewindPoint([this] { DoWork(); });
if (rewinded) {
goal_reached = true;
Fiber::YieldTo(fiber1, *thread_fiber);
}
rewinded = true;
fiber1->Rewind();
}
std::shared_ptr<Common::Fiber> fiber1;
std::shared_ptr<Common::Fiber> thread_fiber;
bool goal_reached;
bool rewinded;
};
TEST_CASE("Fibers::Rewind", "[common]") {
TestControl4 test_control{};
test_control.Execute();
REQUIRE(test_control.goal_reached);
REQUIRE(test_control.rewinded);
}
} // namespace Common

View File

@@ -1,4 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <atomic>
@@ -537,7 +539,9 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
break;
case Settings::ShaderBackend::SpirV:
ConvertLegacyToGeneric(program, runtime_info);
sources_spirv[stage_index] = EmitSPIRV(profile, runtime_info, program, binding);
sources_spirv[stage_index] =
EmitSPIRV(profile, runtime_info, program, binding,
Settings::values.optimize_spirv_output.GetValue());
break;
}
previous_program = &program;
@@ -596,7 +600,7 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
code = EmitGLASM(profile, info, program);
break;
case Settings::ShaderBackend::SpirV:
code_spirv = EmitSPIRV(profile, program);
code_spirv = EmitSPIRV(profile, program, Settings::values.optimize_spirv_output.GetValue());
break;
}

View File

@@ -1,4 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
@@ -673,7 +675,8 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
const auto runtime_info{MakeRuntimeInfo(programs, key, program, previous_stage)};
ConvertLegacyToGeneric(program, runtime_info);
const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)};
const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding,
Settings::values.optimize_spirv_output.GetValue())};
device.SaveShader(code);
modules[stage_index] = BuildShader(device, code);
if (device.HasDebuggingToolAttached()) {
@@ -767,7 +770,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
}
auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)};
const std::vector<u32> code{EmitSPIRV(profile, program)};
const std::vector<u32> code{
EmitSPIRV(profile, program, Settings::values.optimize_spirv_output.GetValue())};
device.SaveShader(code);
vk::ShaderModule spv_module{BuildShader(device, code)};
if (device.HasDebuggingToolAttached()) {