1
0
mirror of https://git.suyu.dev/suyu/suyu synced 2025-12-08 13:52:08 -06:00

6 Commits

Author SHA1 Message Date
Crimson Hawk
4d5ac18068 Merge branch 'dev' into optimize-spirv 2024-05-29 08:39:36 +08:00
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
17 changed files with 246 additions and 2182 deletions

10
.gitmodules vendored
View File

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

View File

@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: 2024 suyu 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 # SPDX-License-Identifier: GPL-2.0-or-later
cmake_minimum_required(VERSION 3.22) 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_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_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
option(SUYU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) 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) add_definitions(-DHAS_NCE=1)
endif() endif()
set(CMAKE_CXX_STANDARD 20) # Configure C++ standard
set(CMAKE_CXX_STANDARD_REQUIRED ON) # ===========================
# 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/ # Output binaries to bin/
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/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 # 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(enet 1.3 MODULE)
find_package(fmt 9 REQUIRED) find_package(fmt 9 REQUIRED)
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle) 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) find_package(VulkanUtilityLibraries REQUIRED)
endif() 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) if (ENABLE_LIBUSB)
find_package(libusb 1.0.24 MODULE) find_package(libusb 1.0.24 MODULE)
endif() endif()
@@ -344,6 +364,11 @@ if (SUYU_TESTS)
find_package(Catch2 3.0.1 REQUIRED) find_package(Catch2 3.0.1 REQUIRED)
endif() endif()
# boost:asio has functions that require AcceptEx et al
if (MINGW)
find_library(MSWSOCK_LIBRARY mswsock REQUIRED)
endif()
if(ENABLE_OPENSSL) if(ENABLE_OPENSSL)
find_package(OpenSSL 1.1.1 REQUIRED) find_package(OpenSSL 1.1.1 REQUIRED)
endif() endif()
@@ -670,6 +695,8 @@ function(create_target_directory_groups target_name)
endforeach() endforeach()
endfunction() endfunction()
# Prevent boost from linking against libs when building
target_link_libraries(Boost::headers INTERFACE Boost::disable_autolinking)
# Adjustments for MSVC + Ninja # Adjustments for MSVC + Ninja
if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja") if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
add_compile_options( add_compile_options(

View File

@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: 2016 Citra Emulator Project # SPDX-FileCopyrightText: 2016 Citra Emulator Project
# SPDX-FileCopyrightText: 2024 suyu Emulator Project # SPDX-FileCopyrightText: Copyright 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 # SPDX-License-Identifier: GPL-2.0-or-later
# Dynarmic has cmake_minimum_required(3.12) and we may want to override # 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) add_subdirectory(Vulkan-Utility-Libraries)
endif() endif()
# Boost headers # SPIRV-Tools
add_subdirectory(boost-headers) if (YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS)
add_subdirectory(SPIRV-Tools)
endif()
# TZDB (Time Zone Database) # TZDB (Time Zone Database)
add_subdirectory(nx_tzdb) 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: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: 2024 suyu Emulator Project # SPDX-FileCopyrightText: 2024 suyu Emulator Project
# SPDX-FileCopyrightText: 2024 Torzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
if (DEFINED ENV{AZURECIREPO}) if (DEFINED ENV{AZURECIREPO})
@@ -263,7 +262,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
) )
endif() 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) target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
if (ANDROID) if (ANDROID)

View File

@@ -1,52 +1,91 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // 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 // SPDX-License-Identifier: GPL-2.0-or-later
#include <mutex> #include <mutex>
#include "common/assert.h" #include "common/assert.h"
#include "common/fiber.h" #include "common/fiber.h"
#define MINICORO_IMPL #include "common/virtual_buffer.h"
#include "common/minicoro.h"
#include <boost/context/detail/fcontext.hpp>
namespace Common { namespace Common {
constexpr std::size_t default_stack_size = 512 * 1024;
struct Fiber::FiberImpl { struct Fiber::FiberImpl {
FiberImpl() {} FiberImpl() : stack{default_stack_size}, rewind_stack{default_stack_size} {}
VirtualBuffer<u8> stack;
VirtualBuffer<u8> rewind_stack;
std::mutex guard; std::mutex guard;
bool released{};
bool is_thread_fiber{};
Fiber* next_fiber{};
Fiber** next_fiber_ptr;
std::function<void()> entry_point; 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>()} { void Fiber::SetRewindPoint(std::function<void()>&& rewind_func) {
impl->is_thread_fiber = true; 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>()} { Fiber::Fiber(std::function<void()>&& entry_point_func) : impl{std::make_unique<FiberImpl>()} {
impl->entry_point = std::move(entry_point_func); impl->entry_point = std::move(entry_point_func);
auto desc = mco_desc_init( impl->stack_limit = impl->stack.data();
[](mco_coro* coro) { reinterpret_cast<Fiber*>(coro->user_data)->impl->entry_point(); }, 0); impl->rewind_stack_limit = impl->rewind_stack.data();
desc.user_data = this; u8* stack_base = impl->stack_limit + default_stack_size;
mco_result res = mco_create(&impl->context, &desc); impl->context =
ASSERT(res == MCO_SUCCESS); boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc);
} }
Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
Fiber::~Fiber() { Fiber::~Fiber() {
if (impl->released) { if (impl->released) {
return; return;
} }
DestroyPre(); // Make sure the Fiber is not being used
if (impl->is_thread_fiber) { const bool locked = impl->guard.try_lock();
DestroyThreadFiber(); ASSERT_MSG(locked, "Destroying a fiber that's still running");
} else { if (locked) {
DestroyWorkFiber(); impl->guard.unlock();
} }
} }
@@ -55,66 +94,42 @@ void Fiber::Exit() {
if (!impl->is_thread_fiber) { if (!impl->is_thread_fiber) {
return; return;
} }
DestroyPre(); impl->guard.unlock();
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->released = true; impl->released = true;
} }
void Fiber::DestroyWorkFiber() { void Fiber::Rewind() {
mco_result res = mco_destroy(impl->context); ASSERT(impl->rewind_point);
ASSERT(res == MCO_SUCCESS); ASSERT(impl->rewind_context == nullptr);
} u8* stack_base = impl->rewind_stack_limit + default_stack_size;
impl->rewind_context =
void Fiber::DestroyThreadFiber() { boost::context::detail::make_fcontext(stack_base, impl->stack.size(), RewindStartFunc);
if (*impl->next_fiber_ptr) { boost::context::detail::jump_fcontext(impl->rewind_context, this);
*impl->next_fiber_ptr = nullptr;
}
} }
void Fiber::YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to) { 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 (auto from = weak_from.lock()) {
if (!from->impl->is_thread_fiber) { if (from->impl->previous_fiber == nullptr) {
// Set next fiber ASSERT_MSG(false, "previous_fiber is nullptr!");
from->impl->next_fiber = &to; return;
// 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();
} }
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() { 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 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 // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
@@ -8,7 +6,9 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include "common/minicoro.h" namespace boost::context::detail {
struct transfer_t;
}
namespace Common { namespace Common {
@@ -38,21 +38,28 @@ public:
Fiber(Fiber&&) = default; Fiber(Fiber&&) = default;
Fiber& operator=(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); static void YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to);
[[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber(); [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
void SetRewindPoint(std::function<void()>&& rewind_func);
void Rewind();
/// Only call from main thread's fiber /// Only call from main thread's fiber
void Exit(); void Exit();
private: private:
Fiber(); Fiber();
void DestroyPre(); void OnRewind(boost::context::detail::transfer_t& transfer);
void DestroyWorkFiber(); void Start(boost::context::detail::transfer_t& transfer);
void DestroyThreadFiber(); static void FiberStartFunc(boost::context::detail::transfer_t transfer);
static void RewindStartFunc(boost::context::detail::transfer_t transfer);
struct FiberImpl; struct FiberImpl;
std::unique_ptr<FiberImpl> impl; 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 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 // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
@@ -277,6 +279,8 @@ struct Values {
SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache", SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache",
Category::Renderer}; Category::Renderer};
SwitchableSetting<bool> optimize_spirv_output{linkage, false, "optimize_spirv_output",
Category::Renderer};
SwitchableSetting<bool> use_asynchronous_gpu_emulation{ SwitchableSetting<bool> use_asynchronous_gpu_emulation{
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer}; linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage, SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,

View File

@@ -1,4 +1,6 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project # 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 # SPDX-License-Identifier: GPL-2.0-or-later
add_library(shader_recompiler STATIC add_library(shader_recompiler STATIC
@@ -242,7 +244,13 @@ add_library(shader_recompiler STATIC
varying_state.h 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) if (MSVC)
target_compile_options(shader_recompiler PRIVATE target_compile_options(shader_recompiler PRIVATE

View File

@@ -1,4 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // 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 // SPDX-License-Identifier: GPL-2.0-or-later
#include <span> #include <span>
@@ -6,6 +8,7 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <spirv-tools/optimizer.hpp>
#include "common/settings.h" #include "common/settings.h"
#include "shader_recompiler/backend/spirv/emit_spirv.h" #include "shader_recompiler/backend/spirv/emit_spirv.h"
@@ -481,7 +484,7 @@ void PatchPhiNodes(IR::Program& program, EmitContext& ctx) {
} // Anonymous namespace } // Anonymous namespace
std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, 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}; EmitContext ctx{profile, runtime_info, program, bindings};
const Id main{DefineMain(ctx, program)}; const Id main{DefineMain(ctx, program)};
DefineEntryPoint(program, ctx, main); DefineEntryPoint(program, ctx, main);
@@ -493,7 +496,28 @@ std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_in
SetupCapabilities(profile, program.info, ctx); SetupCapabilities(profile, program.info, ctx);
SetupTransformFeedbackCapabilities(ctx, main); SetupTransformFeedbackCapabilities(ctx, main);
PatchPhiNodes(program, ctx); 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) { Id EmitPhi(EmitContext& ctx, IR::Inst* inst) {
@@ -556,4 +580,4 @@ void EmitGetInBoundsFromOp(EmitContext&) {
throw LogicError("Unreachable instruction"); 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 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 // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #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); constexpr u32 RENDERAREA_LAYOUT_OFFSET = offsetof(RenderAreaLayout, render_area);
[[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, [[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; Bindings binding;
return EmitSPIRV(profile, {}, program, binding); return EmitSPIRV(profile, {}, program, binding, optimize);
} }
} // namespace Shader::Backend::SPIRV } // namespace Shader::Backend::SPIRV

View File

@@ -1,4 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // 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 // SPDX-License-Identifier: GPL-2.0-or-later
#include "suyu/configuration/shared_translation.h" #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 " tr("Allows saving shaders to storage for faster loading on following game "
"boots.\nDisabling " "boots.\nDisabling "
"it is only intended for debugging.")); "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( INSERT(
Settings, use_asynchronous_gpu_emulation, tr("Use asynchronous GPU emulation"), Settings, use_asynchronous_gpu_emulation, tr("Use asynchronous GPU emulation"),
tr("Uses an extra CPU thread for rendering.\nThis option should always remain enabled.")); 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 2020 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2024 Torzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <atomic> #include <atomic>
@@ -272,4 +271,43 @@ TEST_CASE("Fibers::StartRace", "[common]") {
REQUIRE(test_control.value3 == 1); 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 } // namespace Common

View File

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

View File

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