diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 5163a16b0..df776e494 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -486,6 +486,7 @@ void Config::ReadRendererValues() { .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.spirv_shader_gen = ReadSetting(QStringLiteral("spirv_shader_gen"), false).toBool(); Settings::values.use_hw_renderer = ReadSetting(QStringLiteral("use_hw_renderer"), true).toBool(); Settings::values.use_hw_shader = ReadSetting(QStringLiteral("use_hw_shader"), true).toBool(); @@ -1006,6 +1007,7 @@ void Config::SaveRendererValues() { static_cast(Settings::GraphicsAPI::OpenGL)); WriteSetting(QStringLiteral("physical_device"), Settings::values.physical_device, 0); 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_shader"), Settings::values.use_hw_shader, true); #ifdef __APPLE__ diff --git a/src/citra_qt/configuration/configure_graphics.cpp b/src/citra_qt/configuration/configure_graphics.cpp index 5285d0688..7e6b82958 100644 --- a/src/citra_qt/configuration/configure_graphics.cpp +++ b/src/citra_qt/configuration/configure_graphics.cpp @@ -85,6 +85,7 @@ void ConfigureGraphics::SetConfiguration() { ui->graphics_api_combo->setCurrentIndex(static_cast(Settings::values.graphics_api)); ui->physical_device_combo->setCurrentIndex(static_cast(Settings::values.physical_device)); ui->toggle_async_recording->setChecked(Settings::values.async_command_recording); + ui->spirv_shader_gen->setChecked(Settings::values.spirv_shader_gen); } void ConfigureGraphics::ApplyConfiguration() { @@ -99,6 +100,7 @@ void ConfigureGraphics::ApplyConfiguration() { static_cast(ui->graphics_api_combo->currentIndex()); Settings::values.physical_device = static_cast(ui->physical_device_combo->currentIndex()); Settings::values.async_command_recording = ui->toggle_async_recording->isChecked(); + Settings::values.spirv_shader_gen = ui->spirv_shader_gen->isChecked(); } void ConfigureGraphics::RetranslateUI() { @@ -121,4 +123,5 @@ void ConfigureGraphics::SetPhysicalDeviceComboVisibility(int index) { const bool is_visible = graphics_api == Settings::GraphicsAPI::Vulkan; ui->physical_device_label->setVisible(is_visible); ui->physical_device_combo->setVisible(is_visible); + ui->spirv_shader_gen->setVisible(is_visible); } diff --git a/src/citra_qt/configuration/configure_graphics.ui b/src/citra_qt/configuration/configure_graphics.ui index 81fe84d5e..313cb82b1 100644 --- a/src/citra_qt/configuration/configure_graphics.ui +++ b/src/citra_qt/configuration/configure_graphics.ui @@ -7,7 +7,7 @@ 0 0 400 - 430 + 513 @@ -70,6 +70,13 @@ + + + + SPIR-V Shader Generation + + + diff --git a/src/core/settings.h b/src/core/settings.h index 933d0cac1..0f06588de 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -167,6 +167,7 @@ struct Values { // Renderer GraphicsAPI graphics_api; u16 physical_device; + bool spirv_shader_gen; bool renderer_debug; bool dump_command_buffers; bool async_command_recording; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index ee64fbf0b..aac3b0860 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -92,7 +92,11 @@ PipelineCache::~PipelineCache() { 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); } @@ -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) { const PicaFSConfig config{regs, instance}; scheduler.Record([this, config](vk::CommandBuffer, vk::CommandBuffer) { - vk::ShaderModule handle = fragment_shaders.Get(config, vk::ShaderStageFlagBits::eFragment, - instance.GetDevice(), ShaderOptimization::Debug); + MICROPROFILE_SCOPE(Vulkan_FragmentGeneration); + + 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; shader_hashes[ProgramType::FS] = config.Hash(); }); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 3ee58eaef..6893a9fe2 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -116,7 +116,10 @@ using ProgrammableVertexShaders = Pica::Shader::ShaderDoubleCache; -using FragmentShaders = +using FragmentShadersGLSL = + Pica::Shader::ShaderCache; + +using FragmentShadersSPV = Pica::Shader::ShaderCache; class Instance; @@ -217,7 +220,8 @@ private: std::array shader_hashes; ProgrammableVertexShaders programmable_vertex_shaders; FixedGeometryShaders fixed_geometry_shaders; - FragmentShaders fragment_shaders; + FragmentShadersGLSL fragment_shaders_glsl; + FragmentShadersSPV fragment_shaders_spv; vk::ShaderModule trivial_vertex_shader; }; diff --git a/src/video_core/renderer_vulkan/vk_shader_gen_spv.cpp b/src/video_core/renderer_vulkan/vk_shader_gen_spv.cpp index d4929d238..dd351c2f1 100644 --- a/src/video_core/renderer_vulkan/vk_shader_gen_spv.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_gen_spv.cpp @@ -893,9 +893,7 @@ void FragmentModule::DefineInterface() { 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 GenerateFragmentShaderSPV(const PicaFSConfig& config) { - MICROPROFILE_SCOPE(Vulkan_FragmentGenerationSPV); FragmentModule module{config}; module.Generate(); return module.Assemble(); diff --git a/src/video_core/renderer_vulkan/vk_shader_util.cpp b/src/video_core/renderer_vulkan/vk_shader_util.cpp index 6d3e19607..76adadf44 100644 --- a/src/video_core/renderer_vulkan/vk_shader_util.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_util.cpp @@ -6,6 +6,7 @@ #include #include #include "common/assert.h" +#include "common/microprofile.h" #include "common/logging/log.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); } - return CompileSPV(out_code, stage, device, level); + return CompileSPV(out_code, device); } -vk::ShaderModule CompileSPV(std::vector code, vk::ShaderStageFlagBits stage, vk::Device device, - ShaderOptimization) { +MICROPROFILE_DEFINE(Vulkan_SPVCompilation, "Vulkan", "SPIR-V Shader Compilation", MP_RGB(100, 255, 52)); +vk::ShaderModule CompileSPV(std::vector code, vk::Device device) { + MICROPROFILE_SCOPE(Vulkan_SPVCompilation); const vk::ShaderModuleCreateInfo shader_info = {.codeSize = code.size() * sizeof(u32), .pCode = code.data()}; try { diff --git a/src/video_core/renderer_vulkan/vk_shader_util.h b/src/video_core/renderer_vulkan/vk_shader_util.h index 6ea356d8c..f21299948 100644 --- a/src/video_core/renderer_vulkan/vk_shader_util.h +++ b/src/video_core/renderer_vulkan/vk_shader_util.h @@ -13,7 +13,6 @@ enum class ShaderOptimization { High = 0, Debug = 1 }; vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, vk::Device device, ShaderOptimization level); -vk::ShaderModule CompileSPV(std::vector code, vk::ShaderStageFlagBits stage, vk::Device device, - ShaderOptimization level); +vk::ShaderModule CompileSPV(std::vector code, vk::Device device); } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index f52821fd4..539851b67 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -189,7 +189,14 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma .samples = vk::SampleCountFlagBits::e1, .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{}; VkImageCreateInfo unsafe_image_info = static_cast(image_info);