diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index f863a2b911..0de2d08839 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -550,6 +550,7 @@ target_sources(rpcs3_emu PRIVATE RSX/Program/GLSLCommon.cpp RSX/Program/ProgramStateCache.cpp RSX/Program/program_util.cpp + RSX/Program/ShaderInterpreter.cpp RSX/Program/SPIRVCommon.cpp RSX/Program/VertexProgramDecompiler.cpp RSX/GSFrameBase.cpp diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index c1acabd601..7efcb199d1 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -332,8 +332,6 @@ void GLGSRender::on_init_thread() { m_vertex_instructions_buffer->create(gl::buffer::target::ssbo, 16 * 0x100000); m_fragment_instructions_buffer->create(gl::buffer::target::ssbo, 16 * 0x100000); - - m_shader_interpreter.create(); } if (gl_caps.vendor_AMD) @@ -410,21 +408,31 @@ void GLGSRender::on_init_thread() } ); - if (!m_overlay_manager) + if (shadermode == shader_mode::async_with_interpreter || + shadermode == shader_mode::interpreter_only) { - m_frame->hide(); - m_shaders_cache->load(nullptr); - m_frame->show(); + std::unique_ptr dlg = m_overlay_manager + ? std::make_unique(this) + : std::make_unique(); + m_shader_interpreter.create(dlg.get()); } - else - { - rsx::shader_loading_dialog_native dlg(this); - m_shaders_cache->load(&dlg); + if (shadermode != shader_mode::interpreter_only) + { + if (!m_overlay_manager) + { + m_frame->hide(); + m_shaders_cache->load(nullptr); + m_frame->show(); + } + else + { + rsx::shader_loading_dialog_native dlg(this); + m_shaders_cache->load(&dlg); + } } } - void GLGSRender::on_exit() { // Destroy internal RSX state, may call upon this->do_local_task diff --git a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp index fa5b3627c4..9c19757347 100644 --- a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp +++ b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp @@ -3,9 +3,11 @@ #include "GLTextureCache.h" #include "GLVertexProgram.h" #include "GLFragmentProgram.h" -#include "../rsx_methods.h" -#include "../Program/ShaderInterpreter.h" -#include "../Program/GLSLCommon.h" + +#include "Emu/RSX/rsx_methods.h" +#include "Emu/RSX/Overlays/Shaders/shader_loading_dialog.h" +#include "Emu/RSX/Program/ShaderInterpreter.h" +#include "Emu/RSX/Program/GLSLCommon.h" namespace gl { @@ -44,10 +46,25 @@ namespace gl } } - void shader_interpreter::create() + void shader_interpreter::create(rsx::shader_loading_dialog* dlg) { - build_program(::program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES); - build_program(::program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES | ::program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT); + dlg->create("Precompiling interpreter variants.\nPlease wait...", "Shader Compilation"); + + const auto variants = program_common::interpreter::get_interpreter_variants(); + const u32 limit = ::size32(variants); + dlg->set_limit(0, limit); + dlg->set_limit(1, 1); + + u32 ctr = 0; + for (auto& variant : variants) + { + build_program(variant.first | variant.second); + dlg->update_msg(0, fmt::format("Building variant %u of %u...", ++ctr, limit)); + dlg->inc_value(0, 1); + } + + dlg->inc_value(1, 1); + dlg->refresh(); } void shader_interpreter::destroy() diff --git a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h index 62075dbb4b..92cce63a6b 100644 --- a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h +++ b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.h @@ -5,6 +5,11 @@ #include +namespace rsx +{ + struct shader_loading_dialog; +} + namespace gl { using namespace ::glsl; @@ -78,7 +83,7 @@ namespace gl interpreter::cached_program* m_current_interpreter = nullptr; public: - void create(); + void create(rsx::shader_loading_dialog* dlg); void destroy(); void update_fragment_textures(const std::array, 16>& descriptors, u16 reference_mask, u32* out); diff --git a/rpcs3/Emu/RSX/Program/ShaderInterpreter.cpp b/rpcs3/Emu/RSX/Program/ShaderInterpreter.cpp new file mode 100644 index 0000000000..a01171b3e6 --- /dev/null +++ b/rpcs3/Emu/RSX/Program/ShaderInterpreter.cpp @@ -0,0 +1,58 @@ +#include "stdafx.h" +#include "ShaderInterpreter.h" + +#include + +namespace program_common::interpreter +{ + std::vector get_interpreter_variants() + { + // Separable passes to fetch all possible variants + std::unordered_set fs_masks; + for (u32 fs_opt = COMPILER_OPT_FS_MIN, fs_opt_bit = fs_opt; + fs_opt <= COMPILER_OPT_FS_MAX; fs_opt++, fs_opt_bit <<= 1) + { + if (fs_opt_bit & COMPILER_OPT_ALPHA_TEST_MASK) + { + continue; + } + + fs_masks.insert(fs_opt); + } + + // Now we add in the alpha testing variants for all fs variants. + // Only one alpha test type is usable at once + std::unordered_set fs_alpha_test_masks; + for (u32 alpha_test_bit = COMPILER_OPT_ENABLE_ALPHA_TEST_GE; + alpha_test_bit <= COMPILER_OPT_ENABLE_ALPHA_TEST_NE; + alpha_test_bit <<= 1) + { + for (const auto& mask : fs_masks) + { + fs_alpha_test_masks.insert(mask | alpha_test_bit); + } + } + + // VS + std::unordered_set vs_masks; + for (u32 vs_opt = COMPILER_OPT_VS_MIN; vs_opt <= COMPILER_OPT_VS_MAX; ++vs_opt) + { + vs_masks.insert(vs_opt); + } + + // Merge all FS variants + fs_masks.merge(fs_alpha_test_masks); + + // Prepare outputs + std::vector results; + for (const auto& vs_opt : vs_masks) + { + for (const auto& fs_opt : fs_masks) + { + results.push_back({ vs_opt, fs_opt }); + } + } + + return results; + } +} diff --git a/rpcs3/Emu/RSX/Program/ShaderInterpreter.h b/rpcs3/Emu/RSX/Program/ShaderInterpreter.h index f89c058dec..d31da660b1 100644 --- a/rpcs3/Emu/RSX/Program/ShaderInterpreter.h +++ b/rpcs3/Emu/RSX/Program/ShaderInterpreter.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace program_common { namespace interpreter @@ -22,7 +24,15 @@ namespace program_common COMPILER_OPT_ENABLE_INSTANCING = (1 << 13), COMPILER_OPT_ENABLE_VTX_TEXTURES = (1 << 14), - COMPILER_OPT_MAX = COMPILER_OPT_ENABLE_VTX_TEXTURES + // Meta + COMPILER_OPT_MAX = COMPILER_OPT_ENABLE_VTX_TEXTURES, + COMPILER_OPT_ALPHA_TEST_MASK = (0b111111 << COMPILER_OPT_ENABLE_ALPHA_TEST_GE), + + // Bounds + COMPILER_OPT_FS_MAX = COMPILER_OPT_ENABLE_STIPPLING, + COMPILER_OPT_FS_MIN = COMPILER_OPT_ENABLE_TEXTURES, + COMPILER_OPT_VS_MAX = COMPILER_OPT_ENABLE_VTX_TEXTURES, + COMPILER_OPT_VS_MIN = COMPILER_OPT_ENABLE_INSTANCING, }; static std::string get_vertex_interpreter() @@ -40,5 +50,8 @@ namespace program_common ; return s; } + + using interpreter_variant_t = std::pair; + std::vector get_interpreter_variants(); } }