citra_qt: Add SPIR-V shader option

This commit is contained in:
GPUCode
2022-11-07 22:18:21 +02:00
parent 75b6c5b4c5
commit ddfae0025c
10 changed files with 50 additions and 14 deletions

View File

@ -486,6 +486,7 @@ void Config::ReadRendererValues() {
.toUInt()); .toUInt());
Settings::values.physical_device = ReadSetting(QStringLiteral("physical_device"), 0).toUInt(); Settings::values.physical_device = ReadSetting(QStringLiteral("physical_device"), 0).toUInt();
Settings::values.async_command_recording = ReadSetting(QStringLiteral("async_command_recording"), true).toBool(); Settings::values.async_command_recording = ReadSetting(QStringLiteral("async_command_recording"), true).toBool();
Settings::values.spirv_shader_gen = ReadSetting(QStringLiteral("spirv_shader_gen"), false).toBool();
Settings::values.use_hw_renderer = Settings::values.use_hw_renderer =
ReadSetting(QStringLiteral("use_hw_renderer"), true).toBool(); ReadSetting(QStringLiteral("use_hw_renderer"), true).toBool();
Settings::values.use_hw_shader = ReadSetting(QStringLiteral("use_hw_shader"), true).toBool(); Settings::values.use_hw_shader = ReadSetting(QStringLiteral("use_hw_shader"), true).toBool();
@ -1006,6 +1007,7 @@ void Config::SaveRendererValues() {
static_cast<u32>(Settings::GraphicsAPI::OpenGL)); static_cast<u32>(Settings::GraphicsAPI::OpenGL));
WriteSetting(QStringLiteral("physical_device"), Settings::values.physical_device, 0); WriteSetting(QStringLiteral("physical_device"), Settings::values.physical_device, 0);
WriteSetting(QStringLiteral("async_command_recording"), Settings::values.async_command_recording, true); WriteSetting(QStringLiteral("async_command_recording"), Settings::values.async_command_recording, true);
WriteSetting(QStringLiteral("spirv_shader_gen"), Settings::values.spirv_shader_gen, false);
WriteSetting(QStringLiteral("use_hw_renderer"), Settings::values.use_hw_renderer, true); WriteSetting(QStringLiteral("use_hw_renderer"), Settings::values.use_hw_renderer, true);
WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, true); WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, true);
#ifdef __APPLE__ #ifdef __APPLE__

View File

@ -85,6 +85,7 @@ void ConfigureGraphics::SetConfiguration() {
ui->graphics_api_combo->setCurrentIndex(static_cast<int>(Settings::values.graphics_api)); ui->graphics_api_combo->setCurrentIndex(static_cast<int>(Settings::values.graphics_api));
ui->physical_device_combo->setCurrentIndex(static_cast<int>(Settings::values.physical_device)); ui->physical_device_combo->setCurrentIndex(static_cast<int>(Settings::values.physical_device));
ui->toggle_async_recording->setChecked(Settings::values.async_command_recording); ui->toggle_async_recording->setChecked(Settings::values.async_command_recording);
ui->spirv_shader_gen->setChecked(Settings::values.spirv_shader_gen);
} }
void ConfigureGraphics::ApplyConfiguration() { void ConfigureGraphics::ApplyConfiguration() {
@ -99,6 +100,7 @@ void ConfigureGraphics::ApplyConfiguration() {
static_cast<Settings::GraphicsAPI>(ui->graphics_api_combo->currentIndex()); static_cast<Settings::GraphicsAPI>(ui->graphics_api_combo->currentIndex());
Settings::values.physical_device = static_cast<u16>(ui->physical_device_combo->currentIndex()); Settings::values.physical_device = static_cast<u16>(ui->physical_device_combo->currentIndex());
Settings::values.async_command_recording = ui->toggle_async_recording->isChecked(); Settings::values.async_command_recording = ui->toggle_async_recording->isChecked();
Settings::values.spirv_shader_gen = ui->spirv_shader_gen->isChecked();
} }
void ConfigureGraphics::RetranslateUI() { void ConfigureGraphics::RetranslateUI() {
@ -121,4 +123,5 @@ void ConfigureGraphics::SetPhysicalDeviceComboVisibility(int index) {
const bool is_visible = graphics_api == Settings::GraphicsAPI::Vulkan; const bool is_visible = graphics_api == Settings::GraphicsAPI::Vulkan;
ui->physical_device_label->setVisible(is_visible); ui->physical_device_label->setVisible(is_visible);
ui->physical_device_combo->setVisible(is_visible); ui->physical_device_combo->setVisible(is_visible);
ui->spirv_shader_gen->setVisible(is_visible);
} }

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>400</width>
<height>430</height> <height>513</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
@ -70,6 +70,13 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QCheckBox" name="spirv_shader_gen">
<property name="text">
<string>SPIR-V Shader Generation</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -167,6 +167,7 @@ struct Values {
// Renderer // Renderer
GraphicsAPI graphics_api; GraphicsAPI graphics_api;
u16 physical_device; u16 physical_device;
bool spirv_shader_gen;
bool renderer_debug; bool renderer_debug;
bool dump_command_buffers; bool dump_command_buffers;
bool async_command_recording; bool async_command_recording;

View File

@ -92,7 +92,11 @@ PipelineCache::~PipelineCache() {
device.destroyShaderModule(module); device.destroyShaderModule(module);
} }
for (auto& [key, module] : fragment_shaders.shaders) { for (auto& [key, module] : fragment_shaders_glsl.shaders) {
device.destroyShaderModule(module);
}
for (auto& [key, module] : fragment_shaders_spv.shaders) {
device.destroyShaderModule(module); device.destroyShaderModule(module);
} }
@ -244,12 +248,21 @@ void PipelineCache::UseTrivialGeometryShader() {
}); });
} }
MICROPROFILE_DEFINE(Vulkan_FragmentGeneration, "Vulkan", "Fragment Shader Compilation", MP_RGB(255, 100, 100));
void PipelineCache::UseFragmentShader(const Pica::Regs& regs) { void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
const PicaFSConfig config{regs, instance}; const PicaFSConfig config{regs, instance};
scheduler.Record([this, config](vk::CommandBuffer, vk::CommandBuffer) { scheduler.Record([this, config](vk::CommandBuffer, vk::CommandBuffer) {
vk::ShaderModule handle = fragment_shaders.Get(config, vk::ShaderStageFlagBits::eFragment, MICROPROFILE_SCOPE(Vulkan_FragmentGeneration);
instance.GetDevice(), ShaderOptimization::Debug);
vk::ShaderModule handle{};
if (Settings::values.spirv_shader_gen) {
handle = fragment_shaders_spv.Get(config, instance.GetDevice());
} else {
handle = fragment_shaders_glsl.Get(config, vk::ShaderStageFlagBits::eFragment,
instance.GetDevice(), ShaderOptimization::Debug);
}
current_shaders[ProgramType::FS] = handle; current_shaders[ProgramType::FS] = handle;
shader_hashes[ProgramType::FS] = config.Hash(); shader_hashes[ProgramType::FS] = config.Hash();
}); });

View File

@ -116,7 +116,10 @@ using ProgrammableVertexShaders = Pica::Shader::ShaderDoubleCache<PicaVSConfig,
using FixedGeometryShaders = Pica::Shader::ShaderCache<PicaFixedGSConfig, vk::ShaderModule, using FixedGeometryShaders = Pica::Shader::ShaderCache<PicaFixedGSConfig, vk::ShaderModule,
&Compile, &GenerateFixedGeometryShader>; &Compile, &GenerateFixedGeometryShader>;
using FragmentShaders = using FragmentShadersGLSL =
Pica::Shader::ShaderCache<PicaFSConfig, vk::ShaderModule, &Compile, &GenerateFragmentShader>;
using FragmentShadersSPV =
Pica::Shader::ShaderCache<PicaFSConfig, vk::ShaderModule, &CompileSPV, &GenerateFragmentShaderSPV>; Pica::Shader::ShaderCache<PicaFSConfig, vk::ShaderModule, &CompileSPV, &GenerateFragmentShaderSPV>;
class Instance; class Instance;
@ -217,7 +220,8 @@ private:
std::array<u64, MAX_SHADER_STAGES> shader_hashes; std::array<u64, MAX_SHADER_STAGES> shader_hashes;
ProgrammableVertexShaders programmable_vertex_shaders; ProgrammableVertexShaders programmable_vertex_shaders;
FixedGeometryShaders fixed_geometry_shaders; FixedGeometryShaders fixed_geometry_shaders;
FragmentShaders fragment_shaders; FragmentShadersGLSL fragment_shaders_glsl;
FragmentShadersSPV fragment_shaders_spv;
vk::ShaderModule trivial_vertex_shader; vk::ShaderModule trivial_vertex_shader;
}; };

View File

@ -893,9 +893,7 @@ void FragmentModule::DefineInterface() {
Decorate(gl_frag_depth_id, spv::Decoration::BuiltIn, spv::BuiltIn::FragDepth); Decorate(gl_frag_depth_id, spv::Decoration::BuiltIn, spv::BuiltIn::FragDepth);
} }
MICROPROFILE_DEFINE(Vulkan_FragmentGenerationSPV, "Vulkan", "SPIRV Fragment Shader Compilation", MP_RGB(255, 100, 100));
std::vector<u32> GenerateFragmentShaderSPV(const PicaFSConfig& config) { std::vector<u32> GenerateFragmentShaderSPV(const PicaFSConfig& config) {
MICROPROFILE_SCOPE(Vulkan_FragmentGenerationSPV);
FragmentModule module{config}; FragmentModule module{config};
module.Generate(); module.Generate();
return module.Assemble(); return module.Assemble();

View File

@ -6,6 +6,7 @@
#include <glslang/Include/ResourceLimits.h> #include <glslang/Include/ResourceLimits.h>
#include <glslang/Public/ShaderLang.h> #include <glslang/Public/ShaderLang.h>
#include "common/assert.h" #include "common/assert.h"
#include "common/microprofile.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "video_core/renderer_vulkan/vk_shader_util.h" #include "video_core/renderer_vulkan/vk_shader_util.h"
@ -217,11 +218,12 @@ vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, v
LOG_INFO(Render_Vulkan, "SPIR-V conversion messages: {}", spv_messages); LOG_INFO(Render_Vulkan, "SPIR-V conversion messages: {}", spv_messages);
} }
return CompileSPV(out_code, stage, device, level); return CompileSPV(out_code, device);
} }
vk::ShaderModule CompileSPV(std::vector<u32> code, vk::ShaderStageFlagBits stage, vk::Device device, MICROPROFILE_DEFINE(Vulkan_SPVCompilation, "Vulkan", "SPIR-V Shader Compilation", MP_RGB(100, 255, 52));
ShaderOptimization) { vk::ShaderModule CompileSPV(std::vector<u32> code, vk::Device device) {
MICROPROFILE_SCOPE(Vulkan_SPVCompilation);
const vk::ShaderModuleCreateInfo shader_info = {.codeSize = code.size() * sizeof(u32), const vk::ShaderModuleCreateInfo shader_info = {.codeSize = code.size() * sizeof(u32),
.pCode = code.data()}; .pCode = code.data()};
try { try {

View File

@ -13,7 +13,6 @@ enum class ShaderOptimization { High = 0, Debug = 1 };
vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, vk::Device device, vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, vk::Device device,
ShaderOptimization level); ShaderOptimization level);
vk::ShaderModule CompileSPV(std::vector<u32> code, vk::ShaderStageFlagBits stage, vk::Device device, vk::ShaderModule CompileSPV(std::vector<u32> code, vk::Device device);
ShaderOptimization level);
} // namespace Vulkan } // namespace Vulkan

View File

@ -189,7 +189,14 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
.samples = vk::SampleCountFlagBits::e1, .samples = vk::SampleCountFlagBits::e1,
.usage = usage}; .usage = usage};
const VmaAllocationCreateInfo alloc_info = {.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE}; const VmaAllocationCreateInfo alloc_info = {
.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
.requiredFlags = 0,
.preferredFlags = 0,
.pool = VK_NULL_HANDLE,
.pUserData = nullptr,
};
VkImage unsafe_image{}; VkImage unsafe_image{};
VkImageCreateInfo unsafe_image_info = static_cast<VkImageCreateInfo>(image_info); VkImageCreateInfo unsafe_image_info = static_cast<VkImageCreateInfo>(image_info);