rsx/gl: Implement shader interpreter variant precompilation
This commit is contained in:
@@ -550,6 +550,7 @@ target_sources(rpcs3_emu PRIVATE
|
|||||||
RSX/Program/GLSLCommon.cpp
|
RSX/Program/GLSLCommon.cpp
|
||||||
RSX/Program/ProgramStateCache.cpp
|
RSX/Program/ProgramStateCache.cpp
|
||||||
RSX/Program/program_util.cpp
|
RSX/Program/program_util.cpp
|
||||||
|
RSX/Program/ShaderInterpreter.cpp
|
||||||
RSX/Program/SPIRVCommon.cpp
|
RSX/Program/SPIRVCommon.cpp
|
||||||
RSX/Program/VertexProgramDecompiler.cpp
|
RSX/Program/VertexProgramDecompiler.cpp
|
||||||
RSX/GSFrameBase.cpp
|
RSX/GSFrameBase.cpp
|
||||||
|
|||||||
@@ -332,8 +332,6 @@ void GLGSRender::on_init_thread()
|
|||||||
{
|
{
|
||||||
m_vertex_instructions_buffer->create(gl::buffer::target::ssbo, 16 * 0x100000);
|
m_vertex_instructions_buffer->create(gl::buffer::target::ssbo, 16 * 0x100000);
|
||||||
m_fragment_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)
|
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();
|
std::unique_ptr<rsx::shader_loading_dialog> dlg = m_overlay_manager
|
||||||
m_shaders_cache->load(nullptr);
|
? std::make_unique<rsx::shader_loading_dialog_native>(this)
|
||||||
m_frame->show();
|
: std::make_unique<rsx::shader_loading_dialog>();
|
||||||
|
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()
|
void GLGSRender::on_exit()
|
||||||
{
|
{
|
||||||
// Destroy internal RSX state, may call upon this->do_local_task
|
// Destroy internal RSX state, may call upon this->do_local_task
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
#include "GLTextureCache.h"
|
#include "GLTextureCache.h"
|
||||||
#include "GLVertexProgram.h"
|
#include "GLVertexProgram.h"
|
||||||
#include "GLFragmentProgram.h"
|
#include "GLFragmentProgram.h"
|
||||||
#include "../rsx_methods.h"
|
|
||||||
#include "../Program/ShaderInterpreter.h"
|
#include "Emu/RSX/rsx_methods.h"
|
||||||
#include "../Program/GLSLCommon.h"
|
#include "Emu/RSX/Overlays/Shaders/shader_loading_dialog.h"
|
||||||
|
#include "Emu/RSX/Program/ShaderInterpreter.h"
|
||||||
|
#include "Emu/RSX/Program/GLSLCommon.h"
|
||||||
|
|
||||||
namespace gl
|
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);
|
dlg->create("Precompiling interpreter variants.\nPlease wait...", "Shader Compilation");
|
||||||
build_program(::program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES | ::program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT);
|
|
||||||
|
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()
|
void shader_interpreter::destroy()
|
||||||
|
|||||||
@@ -5,6 +5,11 @@
|
|||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace rsx
|
||||||
|
{
|
||||||
|
struct shader_loading_dialog;
|
||||||
|
}
|
||||||
|
|
||||||
namespace gl
|
namespace gl
|
||||||
{
|
{
|
||||||
using namespace ::glsl;
|
using namespace ::glsl;
|
||||||
@@ -78,7 +83,7 @@ namespace gl
|
|||||||
interpreter::cached_program* m_current_interpreter = nullptr;
|
interpreter::cached_program* m_current_interpreter = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void create();
|
void create(rsx::shader_loading_dialog* dlg);
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
void update_fragment_textures(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, 16>& descriptors, u16 reference_mask, u32* out);
|
void update_fragment_textures(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, 16>& descriptors, u16 reference_mask, u32* out);
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "ShaderInterpreter.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace program_common::interpreter
|
||||||
|
{
|
||||||
|
std::vector<interpreter_variant_t> get_interpreter_variants()
|
||||||
|
{
|
||||||
|
// Separable passes to fetch all possible variants
|
||||||
|
std::unordered_set<u32> 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<u32> 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<u32> 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<interpreter_variant_t> results;
|
||||||
|
for (const auto& vs_opt : vs_masks)
|
||||||
|
{
|
||||||
|
for (const auto& fs_opt : fs_masks)
|
||||||
|
{
|
||||||
|
results.push_back({ vs_opt, fs_opt });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <util/types.hpp>
|
||||||
|
|
||||||
namespace program_common
|
namespace program_common
|
||||||
{
|
{
|
||||||
namespace interpreter
|
namespace interpreter
|
||||||
@@ -22,7 +24,15 @@ namespace program_common
|
|||||||
COMPILER_OPT_ENABLE_INSTANCING = (1 << 13),
|
COMPILER_OPT_ENABLE_INSTANCING = (1 << 13),
|
||||||
COMPILER_OPT_ENABLE_VTX_TEXTURES = (1 << 14),
|
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()
|
static std::string get_vertex_interpreter()
|
||||||
@@ -40,5 +50,8 @@ namespace program_common
|
|||||||
;
|
;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using interpreter_variant_t = std::pair<u32, u32>;
|
||||||
|
std::vector<interpreter_variant_t> get_interpreter_variants();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user