video_core: Implement Vulkan SPIR-V Optimization on Desktop OSes
Some checks failed
mandarine-build / source (push) Has been cancelled
mandarine-build / linux (appimage) (push) Has been cancelled
mandarine-build / linux (fresh) (push) Has been cancelled
mandarine-build / macos (arm64) (push) Has been cancelled
mandarine-build / macos (x86_64) (push) Has been cancelled
mandarine-build / windows (msvc) (push) Has been cancelled
mandarine-build / windows (msys2) (push) Has been cancelled
mandarine-build / android (push) Has been cancelled
mandarine-format / clang-format (push) Has been cancelled
mandarine-build / macos-universal (push) Has been cancelled
mandarine-build / release (push) Has been cancelled

This commit is contained in:
spectranator 2024-11-14 18:03:56 +01:00 committed by Gamer64
parent 17422ff2c7
commit e6f0b73d23
8 changed files with 106 additions and 3 deletions

3
.gitmodules vendored
View File

@ -94,3 +94,6 @@
[submodule "externals/oboe"]
path = externals/oboe
url = https://github.com/google/oboe.git
[submodule "externals/SPIRV-Tools"]
path = externals/SPIRV-Tools
url = https://github.com/KhronosGroup/SPIRV-Tools.git

View File

@ -427,6 +427,10 @@ if (ENABLE_VULKAN)
target_include_directories(vulkan-headers SYSTEM INTERFACE ./vulkan-headers/include)
endif()
# SPIRV-Tools
add_library(SPIRV-Tools INTERFACE)
target_include_directories(SPIRV-Tools SYSTEM INTERFACE ./SPIRV-Tools/include)
# adrenotools
if (ANDROID AND "arm64" IN_LIST ARCHITECTURE)
add_subdirectory(libadrenotools)

1
externals/SPIRV-Tools vendored Submodule

@ -0,0 +1 @@
Subproject commit 35e5f1160ecd2b963682e14e869001a60160a0c4

View File

@ -471,6 +471,21 @@ struct Values {
Setting<bool> renderer_debug{false, "renderer_debug"};
Setting<bool> dump_command_buffers{false, "dump_command_buffers"};
SwitchableSetting<bool> spirv_shader_gen{true, "spirv_shader_gen"};
// SPIR-V Optimization only works on Desktop OSes for now
#ifdef __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
SwitchableSetting<bool> optimize_spirv_output{false, "optimize_spirv_output"};
#elif TARGET_OS_MAC
SwitchableSetting<bool> optimize_spirv_output{true, "optimize_spirv_output"};
#endif
#elif __ANDROID__
SwitchableSetting<bool> optimize_spirv_output{false, "optimize_spirv_output"};
#else
SwitchableSetting<bool> optimize_spirv_output{true, "optimize_spirv_output"};
#endif
SwitchableSetting<bool> async_shader_compilation{false, "async_shader_compilation"};
SwitchableSetting<bool> async_presentation{true, "async_presentation"};
SwitchableSetting<bool> use_hw_shader{true, "use_hw_shader"};

View File

@ -3,12 +3,30 @@
// Refer to the license.txt file included.
#include <memory>
#include <utility>
#include <vector>
#include <SPIRV/GlslangToSpv.h>
#include <glslang/Include/ResourceLimits.h>
#include <glslang/Public/ShaderLang.h>
// The optimizer included in SPIRV-Tools only works on Desktop OSes
#if defined(_WIN32) || (defined(__linux__) && !defined(__ANDROID__))
#define OPTIMIZE_SPIRV
#elif defined(__APPLE__)
#include <TargetConditionals.h>
#if TARGET_OS_OSX
#define OPTIMIZE_SPIRV
#endif
#endif
#ifdef OPTIMIZE_SPIRV
#include <spirv-tools/optimizer.hpp>
#endif
#include "common/assert.h"
#include "common/literals.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
namespace Vulkan {
@ -159,6 +177,35 @@ bool InitializeCompiler() {
}
} // Anonymous namespace
/**
* NOTE: The libraries included in SPIRV-Tools only work on Windows, Linux and MacOS.
* @brief Optimizes SPIR-V code (but only on Desktop)
* @param code The string containing SPIR-V code
*/
std::vector<u32> OptimizeSPIRV(std::vector<u32> code) {
std::vector<u32> result = code;
#ifdef OPTIMIZE_SPIRV
std::vector<u32> spirv = code;
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);
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);
}
#endif
return result;
}
/**
* @brief Compiles GLSL into SPIRV
* @param code The string containing GLSL code.
@ -222,7 +269,14 @@ std::vector<u32> CompileGLSLtoSPIRV(std::string_view code, vk::ShaderStageFlagBi
LOG_INFO(Render_Vulkan, "SPIR-V conversion messages: {}", spv_messages);
}
return out_code;
// Final pass through SPIRV-Optimizer
if (!Settings::values.optimize_spirv_output.GetValue()) {
return out_code;
} else {
std::vector<u32> result;
result = OptimizeSPIRV(out_code);
return result;
}
}
vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, vk::Device device,

View File

@ -10,6 +10,12 @@
namespace Vulkan {
/**
* @brief Optimizes SPIR-V code
* @param code The string containing SPIR-V code
*/
std::vector<u32> OptimizeSPIRV(std::vector<u32> code);
/**
* @brief Compiles GLSL into SPIRV
* @param code The string containing GLSL code.

View File

@ -3,6 +3,8 @@
// Refer to the license.txt file included.
#include <boost/container/small_vector.hpp>
#include "common/settings.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
#include "video_core/shader/generator/pica_fs_config.h"
#include "video_core/shader/generator/spv_fs_shader_gen.h"
@ -1605,7 +1607,15 @@ void FragmentModule::DefineInterface() {
std::vector<u32> GenerateFragmentShader(const FSConfig& config, const Profile& profile) {
FragmentModule module{config, profile};
module.Generate();
return module.Assemble();
// Run through SPIRV-Optimizer
if (!Settings::values.optimize_spirv_output.GetValue()) {
return module.Assemble();
} else {
std::vector<u32> result;
result = Vulkan::OptimizeSPIRV(module.Assemble());
return result;
}
}
} // namespace Pica::Shader::Generator::SPIRV

View File

@ -2,7 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/settings.h"
#include "video_core/pica/regs_rasterizer.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
#include "video_core/shader/generator/shader_gen.h"
#include "video_core/shader/generator/spv_shader_gen.h"
@ -267,7 +269,15 @@ std::vector<u32> GenerateTrivialVertexShader(bool use_clip_planes) {
}
}
});
return module.Assemble();
// Run through SPIR-V Optimizer
if (!Settings::values.optimize_spirv_output.GetValue()) {
return module.Assemble();
} else {
std::vector<u32> result;
result = Vulkan::OptimizeSPIRV(module.Assemble());
return result;
}
}
} // namespace Pica::Shader::Generator::SPIRV