rsx/gl: Upgrade interpreter model to use a minimal set of reusable pipelines as a base

- We generate optimized variants in the background if we have a partial miss
- A full miss is impossible
This commit is contained in:
kd-11 2026-04-12 20:00:20 +03:00 committed by kd-11
parent 5c4b0a165b
commit af7ae45888
5 changed files with 248 additions and 82 deletions

View File

@ -13,6 +13,7 @@
namespace gl namespace gl
{ {
using glsl::shader; using glsl::shader;
using enum program_common::interpreter::compiler_option;
namespace interpreter namespace interpreter
{ {
@ -52,14 +53,25 @@ namespace gl
dlg->create("Precompiling interpreter variants.\nPlease wait...", "Shader Compilation"); dlg->create("Precompiling interpreter variants.\nPlease wait...", "Shader Compilation");
const auto variants = program_common::interpreter::get_interpreter_variants(); const auto variants = program_common::interpreter::get_interpreter_variants();
const u32 limit = ::size32(variants); const u32 limit1 = ::size32(variants.base_pipelines);
dlg->set_limit(0, limit); const u32 limit2 = ::size32(variants.pipelines);
dlg->set_limit(1, 1); dlg->set_limit(0, limit1);
dlg->set_limit(1, limit2);
atomic_t<u32> ctr = 0; atomic_t<u32> ctr = 0;
auto progress_hook = [&](interpreter::cached_program*) { ctr++; }; auto progress_hook = [&](interpreter::cached_program*) { ctr++; };
for (auto& variant : variants) auto update_progress = [&](u32 stage)
{
const auto completed = ctr.load();
const auto limit = stage ? limit2 : limit1;
const auto message = fmt::format("%s variant %u of %u...", stage ? "Linking" : "Building", ctr.load(), limit);
dlg->update_msg(stage, message);
dlg->set_value(stage, completed);
};
// We only need to build the base "compatible pipeline" pairs.
for (const auto& variant : variants.base_pipelines)
{ {
build_program_async(variant.first | variant.second, progress_hook); build_program_async(variant.first | variant.second, progress_hook);
} }
@ -67,14 +79,47 @@ namespace gl
do do
{ {
std::this_thread::sleep_for(16ms); std::this_thread::sleep_for(16ms);
update_progress(0);
}
while (ctr < limit1);
const u32 completed = ctr.load(); // Show final progress
dlg->update_msg(0, fmt::format("Building variant %u of %u...", completed, limit)); update_progress(0);
dlg->set_value(0, completed);
} while (ctr < limit);
dlg->inc_value(1, 1); // Second stage. Propagate base pipelines to all compatible
dlg->refresh(); ctr = 0;
std::lock_guard lock(m_program_cache_lock);
for (const auto& variant : variants.pipelines)
{
const u64 compiler_options = variant.vs_opts.shader_opt | variant.fs_opts.shader_opt;
if (m_program_cache.find(compiler_options) != m_program_cache.end())
{
// Base variant
continue;
}
const u64 compatible_options = variant.vs_opts.compatible_shader_opts | variant.fs_opts.compatible_shader_opts;
auto base_pipeline = m_program_cache.find(compatible_options);
if (base_pipeline == m_program_cache.end())
{
fmt::throw_exception("Base variant was not found in the cache.");
}
auto data = new interpreter::cached_program();
data->flags |= interpreter::CACHED_PIPE_UNOPTIMIZED;
data->allocator = base_pipeline->second->allocator;
data->vertex_shader = base_pipeline->second->vertex_shader;
data->fragment_shader = base_pipeline->second->fragment_shader;
data->prog = base_pipeline->second->prog;
m_program_cache[compiler_options].reset(data);
}
ctr = limit2;
update_progress(1);
// Minor stall to avoid visual flashing
std::this_thread::sleep_for(16ms);
} }
void shader_interpreter::destroy() void shader_interpreter::destroy()
@ -85,6 +130,16 @@ namespace gl
prog.second->fragment_shader->remove(); prog.second->fragment_shader->remove();
prog.second->prog->remove(); prog.second->prog->remove();
} }
for (auto& shader : m_vs_cache)
{
shader.second->remove();
}
for (auto& shader : m_fs_cache)
{
shader.second->remove();
}
} }
glsl::program* shader_interpreter::get(const interpreter::program_metadata& metadata, u32 vp_ctrl, u32 fp_ctrl) glsl::program* shader_interpreter::get(const interpreter::program_metadata& metadata, u32 vp_ctrl, u32 fp_ctrl)
@ -100,49 +155,51 @@ namespace gl
case rsx::comparison_function::never: case rsx::comparison_function::never:
return nullptr; return nullptr;
case rsx::comparison_function::greater_or_equal: case rsx::comparison_function::greater_or_equal:
opt |= program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_GE; opt |= COMPILER_OPT_ENABLE_ALPHA_TEST_GE;
break; break;
case rsx::comparison_function::greater: case rsx::comparison_function::greater:
opt |= program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_G; opt |= COMPILER_OPT_ENABLE_ALPHA_TEST_G;
break; break;
case rsx::comparison_function::less_or_equal: case rsx::comparison_function::less_or_equal:
opt |= program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_LE; opt |= COMPILER_OPT_ENABLE_ALPHA_TEST_LE;
break; break;
case rsx::comparison_function::less: case rsx::comparison_function::less:
opt |= program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_L; opt |= COMPILER_OPT_ENABLE_ALPHA_TEST_L;
break; break;
case rsx::comparison_function::equal: case rsx::comparison_function::equal:
opt |= program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_EQ; opt |= COMPILER_OPT_ENABLE_ALPHA_TEST_EQ;
break; break;
case rsx::comparison_function::not_equal: case rsx::comparison_function::not_equal:
opt |= program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_NE; opt |= COMPILER_OPT_ENABLE_ALPHA_TEST_NE;
break; break;
} }
} }
if (fp_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_DEPTH_EXPORT; if (fp_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) opt |= COMPILER_OPT_ENABLE_DEPTH_EXPORT;
if (fp_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT; if (fp_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) opt |= COMPILER_OPT_ENABLE_F32_EXPORT;
if (fp_ctrl & RSX_SHADER_CONTROL_USES_KIL) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_KIL; if (fp_ctrl & RSX_SHADER_CONTROL_USES_KIL) opt |= COMPILER_OPT_ENABLE_KIL;
if (metadata.referenced_textures_mask) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES; if (metadata.referenced_textures_mask) opt |= COMPILER_OPT_ENABLE_TEXTURES;
if (metadata.has_branch_instructions) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_FLOW_CTRL; if (metadata.has_branch_instructions) opt |= COMPILER_OPT_ENABLE_FLOW_CTRL;
if (metadata.has_pack_instructions) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_PACKING; if (metadata.has_pack_instructions) opt |= COMPILER_OPT_ENABLE_PACKING;
if (rsx::method_registers.polygon_stipple_enabled()) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_STIPPLING; if (rsx::method_registers.polygon_stipple_enabled()) opt |= COMPILER_OPT_ENABLE_STIPPLING;
if (vp_ctrl & RSX_SHADER_CONTROL_INSTANCED_CONSTANTS) opt |= program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING; if (vp_ctrl & RSX_SHADER_CONTROL_INSTANCED_CONSTANTS) opt |= COMPILER_OPT_ENABLE_INSTANCING;
if (auto it = m_program_cache.find(opt); it != m_program_cache.end()) [[likely]]
{ {
m_current_interpreter = it->second.get(); std::lock_guard lock(m_program_cache_lock);
} if (auto it = m_program_cache.find(opt); it != m_program_cache.end()) [[likely]]
else {
{ m_current_interpreter = it->second.get();
m_current_interpreter = build_program(opt); }
return m_current_interpreter->prog.get();
} }
m_current_interpreter = build_program(opt);
return m_current_interpreter->prog.get(); return m_current_interpreter->prog.get();
} }
void shader_interpreter::build_vs(u64 compiler_options, interpreter::cached_program& prog_data) void shader_interpreter::build_vs(u64 compiler_options, interpreter::cached_program& prog_data)
{ {
compiler_options &= COMPILER_OPT_ALL_VS_MASK;
{ {
std::lock_guard lock(m_vs_cache_lock); std::lock_guard lock(m_vs_cache_lock);
@ -165,7 +222,7 @@ namespace gl
std::string shader_str; std::string shader_str;
ParamArray arr; ParamArray arr;
null_prog.ctrl = (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING) null_prog.ctrl = (compiler_options & COMPILER_OPT_ENABLE_INSTANCING)
? RSX_SHADER_CONTROL_INSTANCED_CONSTANTS ? RSX_SHADER_CONTROL_INSTANCED_CONSTANTS
: 0; : 0;
GLVertexDecompilerThread comp(null_prog, shader_str, arr); GLVertexDecompilerThread comp(null_prog, shader_str, arr);
@ -195,7 +252,7 @@ namespace gl
" uvec4 vp_instructions[];\n" " uvec4 vp_instructions[];\n"
"};\n\n"; "};\n\n";
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING) if (compiler_options & COMPILER_OPT_ENABLE_INSTANCING)
{ {
builder << "#define _ENABLE_INSTANCED_CONSTANTS\n"; builder << "#define _ENABLE_INSTANCED_CONSTANTS\n";
} }
@ -230,20 +287,9 @@ namespace gl
void shader_interpreter::build_fs(u64 compiler_options, interpreter::cached_program& prog_data) void shader_interpreter::build_fs(u64 compiler_options, interpreter::cached_program& prog_data)
{ {
{
std::lock_guard lock(m_fs_cache_lock);
if (auto found = m_fs_cache.find(compiler_options);
found != m_fs_cache.end())
{
prog_data.fragment_shader = found->second;
return;
}
}
// Allocate TIUs // Allocate TIUs
auto& allocator = prog_data.allocator; auto& allocator = prog_data.allocator;
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES) if (compiler_options & COMPILER_OPT_ENABLE_TEXTURES)
{ {
allocator.create(::glsl::program_domain::glsl_fragment_program); allocator.create(::glsl::program_domain::glsl_fragment_program);
if (allocator.max_image_units >= 32) if (allocator.max_image_units >= 32)
@ -277,6 +323,19 @@ namespace gl
} }
} }
// Cache lookup
compiler_options &= COMPILER_OPT_ALL_FS_MASK;
{
std::lock_guard lock(m_fs_cache_lock);
if (auto found = m_fs_cache.find(compiler_options);
found != m_fs_cache.end())
{
prog_data.fragment_shader = found->second;
return;
}
}
u32 len; u32 len;
ParamArray arr; ParamArray arr;
std::string shader_str; std::string shader_str;
@ -291,67 +350,67 @@ namespace gl
::glsl::insert_subheader_block(builder); ::glsl::insert_subheader_block(builder);
comp.insertConstants(builder); comp.insertConstants(builder);
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_GE) if (compiler_options & COMPILER_OPT_ENABLE_ALPHA_TEST_GE)
{ {
builder << "#define ALPHA_TEST_GEQUAL\n"; builder << "#define ALPHA_TEST_GEQUAL\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_G) if (compiler_options & COMPILER_OPT_ENABLE_ALPHA_TEST_G)
{ {
builder << "#define ALPHA_TEST_GREATER\n"; builder << "#define ALPHA_TEST_GREATER\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_LE) if (compiler_options & COMPILER_OPT_ENABLE_ALPHA_TEST_LE)
{ {
builder << "#define ALPHA_TEST_LEQUAL\n"; builder << "#define ALPHA_TEST_LEQUAL\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_L) if (compiler_options & COMPILER_OPT_ENABLE_ALPHA_TEST_L)
{ {
builder << "#define ALPHA_TEST_LESS\n"; builder << "#define ALPHA_TEST_LESS\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_EQ) if (compiler_options & COMPILER_OPT_ENABLE_ALPHA_TEST_EQ)
{ {
builder << "#define ALPHA_TEST_EQUAL\n"; builder << "#define ALPHA_TEST_EQUAL\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_ALPHA_TEST_NE) if (compiler_options & COMPILER_OPT_ENABLE_ALPHA_TEST_NE)
{ {
builder << "#define ALPHA_TEST_NEQUAL\n"; builder << "#define ALPHA_TEST_NEQUAL\n";
} }
if (!(compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT)) if (!(compiler_options & COMPILER_OPT_ENABLE_F32_EXPORT))
{ {
builder << "#define WITH_HALF_OUTPUT_REGISTER\n"; builder << "#define WITH_HALF_OUTPUT_REGISTER\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_DEPTH_EXPORT) if (compiler_options & COMPILER_OPT_ENABLE_DEPTH_EXPORT)
{ {
builder << "#define WITH_DEPTH_EXPORT\n"; builder << "#define WITH_DEPTH_EXPORT\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_FLOW_CTRL) if (compiler_options & COMPILER_OPT_ENABLE_FLOW_CTRL)
{ {
builder << "#define WITH_FLOW_CTRL\n"; builder << "#define WITH_FLOW_CTRL\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_PACKING) if (compiler_options & COMPILER_OPT_ENABLE_PACKING)
{ {
builder << "#define WITH_PACKING\n"; builder << "#define WITH_PACKING\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_KIL) if (compiler_options & COMPILER_OPT_ENABLE_KIL)
{ {
builder << "#define WITH_KIL\n"; builder << "#define WITH_KIL\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_STIPPLING) if (compiler_options & COMPILER_OPT_ENABLE_STIPPLING)
{ {
builder << "#define WITH_STIPPLING\n"; builder << "#define WITH_STIPPLING\n";
} }
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES) if (compiler_options & COMPILER_OPT_ENABLE_TEXTURES)
{ {
builder << "#define WITH_TEXTURES\n\n"; builder << "#define WITH_TEXTURES\n\n";
@ -460,7 +519,7 @@ namespace gl
data->prog->uniforms[0] = GL_STREAM_BUFFER_START + 0; data->prog->uniforms[0] = GL_STREAM_BUFFER_START + 0;
data->prog->uniforms[1] = GL_STREAM_BUFFER_START + 1; data->prog->uniforms[1] = GL_STREAM_BUFFER_START + 1;
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES) if (compiler_options & COMPILER_OPT_ENABLE_TEXTURES)
{ {
// Initialize texture bindings // Initialize texture bindings
int assigned = 0; int assigned = 0;
@ -478,12 +537,13 @@ namespace gl
} }
} }
std::lock_guard lock(m_program_cache_lock);
m_program_cache[compiler_options].reset(data); m_program_cache[compiler_options].reset(data);
} }
bool shader_interpreter::is_interpreter(const glsl::program* program) const bool shader_interpreter::is_interpreter(const glsl::program* program) const
{ {
return (program == m_current_interpreter->prog.get()); return (m_current_interpreter && program == m_current_interpreter->prog.get());
} }
void shader_interpreter::update_fragment_textures( void shader_interpreter::update_fragment_textures(

View File

@ -85,10 +85,10 @@ namespace gl
shared_mutex m_vs_cache_lock; shared_mutex m_vs_cache_lock;
shared_mutex m_fs_cache_lock; shared_mutex m_fs_cache_lock;
shared_mutex m_program_cache_lock;
shader_cache_t m_vs_cache; shader_cache_t m_vs_cache;
shader_cache_t m_fs_cache; shader_cache_t m_fs_cache;
pipeline_cache_t m_program_cache; pipeline_cache_t m_program_cache;
void build_vs(u64 compiler_options, interpreter::cached_program& prog_data); void build_vs(u64 compiler_options, interpreter::cached_program& prog_data);

View File

@ -5,6 +5,20 @@
namespace program_common::interpreter namespace program_common::interpreter
{ {
struct vs_variants_metadata
{
u32 vs_base_mask = 0;
std::unordered_set<u32> vs_base_opts; // Set of options that covers all possible variants regardless of optimization
std::unordered_set<u32> vs_opts; // Full set of options that covers all variants with full optimization
};
struct fs_variants_metadata
{
u32 fs_base_mask = 0;
std::unordered_set<u32> fs_base_opts; // Set of options that covers all possible variants regardless of optimization
std::unordered_set<u32> fs_opts; // Full set of options that covers all variants with full optimization
};
void bitrange_foreach(u32 min, u32 max, std::function<void(u32)> func) void bitrange_foreach(u32 min, u32 max, std::function<void(u32)> func)
{ {
if (max <= min) if (max <= min)
@ -22,50 +36,118 @@ namespace program_common::interpreter
} }
} }
std::vector<interpreter_variant_t> get_interpreter_variants() vs_variants_metadata prepare_vs_variants_data()
{ {
// Separable passes to fetch all possible variants vs_variants_metadata result;
std::unordered_set<u32> fs_masks; result.vs_opts.insert(0);
fs_masks.insert(0); result.vs_base_opts.insert(0);
const u32 base_vs_mask = COMPILER_OPT_ALL_VS_MASK & ~(COMPILER_OPT_VS_EXCL_MASK);
bitrange_foreach(COMPILER_OPT_VS_MIN, COMPILER_OPT_VS_MAX, [&](u32 vs_opt)
{
result.vs_opts.insert(vs_opt);
if (const auto excl_mask = (vs_opt & COMPILER_OPT_VS_EXCL_MASK);
excl_mask != 0)
{
result.vs_base_opts.insert(base_vs_mask | excl_mask);
}
});
result.vs_opts.insert(base_vs_mask);
result.vs_base_opts.insert(base_vs_mask);
result.vs_base_mask = base_vs_mask;
return result;
}
fs_variants_metadata prepare_fs_variants_data()
{
fs_variants_metadata result;
result.fs_opts.insert(0);
result.fs_base_opts.insert(0);
const u32 base_fs_mask = COMPILER_OPT_BASE_FS_MASK & ~(COMPILER_OPT_FS_EXCL_MASK);
bitrange_foreach(COMPILER_OPT_FS_MIN, COMPILER_OPT_FS_MAX, [&](u32 fs_opt) bitrange_foreach(COMPILER_OPT_FS_MIN, COMPILER_OPT_FS_MAX, [&](u32 fs_opt)
{ {
fs_masks.insert(fs_opt); result.fs_opts.insert(fs_opt);
if (const auto excl_mask = (fs_opt & COMPILER_OPT_FS_EXCL_MASK);
excl_mask != 0)
{
result.fs_base_opts.insert(base_fs_mask | excl_mask);
}
}); });
result.fs_opts.insert(base_fs_mask);
result.fs_base_opts.insert(base_fs_mask);
// Now we add in the alpha testing variants for all fs variants. // Now we add in the alpha testing variants for all fs variants.
// Only one alpha test type is usable at once // Only one alpha test type is usable at once
std::unordered_set<u32> fs_alpha_test_masks; std::unordered_set<u32> fs_alpha_test_masks;
std::unordered_set<u32> fs_alpha_test_base_masks;
for (u32 alpha_test_bit = COMPILER_OPT_ENABLE_ALPHA_TEST_GE; for (u32 alpha_test_bit = COMPILER_OPT_ENABLE_ALPHA_TEST_GE;
alpha_test_bit <= COMPILER_OPT_ENABLE_ALPHA_TEST_NE; alpha_test_bit <= COMPILER_OPT_ENABLE_ALPHA_TEST_NE;
alpha_test_bit <<= 1) alpha_test_bit <<= 1)
{ {
for (const auto& mask : fs_masks) for (const auto& mask : result.fs_opts)
{ {
fs_alpha_test_masks.insert(mask | alpha_test_bit); fs_alpha_test_masks.insert(mask | alpha_test_bit);
} }
for (const auto& mask : result.fs_base_opts)
{
fs_alpha_test_base_masks.insert(mask | alpha_test_bit);
}
} }
// VS
std::unordered_set<u32> vs_masks;
vs_masks.insert(0);
bitrange_foreach(COMPILER_OPT_VS_MIN, COMPILER_OPT_VS_MAX, [&](u32 vs_opt)
{
vs_masks.insert(vs_opt);
});
// Merge all FS variants // Merge all FS variants
fs_masks.merge(fs_alpha_test_masks); result.fs_opts.merge(fs_alpha_test_masks);
result.fs_base_opts.merge(fs_alpha_test_base_masks);
result.fs_base_mask = base_fs_mask;
return result;
}
interpreter_variants_t get_interpreter_variants()
{
const auto vs_metadata = prepare_vs_variants_data();
const auto fs_metadata = prepare_fs_variants_data();
const auto& vs_masks = vs_metadata.vs_opts;
const auto& fs_masks = fs_metadata.fs_opts;
const auto base_vs_mask = vs_metadata.vs_base_mask;
const auto base_fs_mask = fs_metadata.fs_base_mask;
// Prepare outputs // Prepare outputs
std::vector<interpreter_variant_t> results; interpreter_variants_t result;
for (const auto& vs_opt : vs_masks) for (const auto& vs_opt : vs_masks)
{ {
for (const auto& fs_opt : fs_masks) for (const auto& fs_opt : fs_masks)
{ {
results.push_back({ vs_opt, fs_opt }); interpreter_pipeline_variant_t variant{};
variant.vs_opts.shader_opt = vs_opt;
variant.vs_opts.compatible_shader_opts = (vs_opt & ~base_vs_mask) | base_vs_mask;
variant.fs_opts.shader_opt = fs_opt;
variant.fs_opts.compatible_shader_opts = (fs_opt & ~base_fs_mask) | base_fs_mask;
result.pipelines.emplace_back(std::move(variant));
} }
} }
return results; // Calculate base pipelines (minimal set)
const auto& vs_base_masks = vs_metadata.vs_base_opts;
const auto& fs_base_masks = fs_metadata.fs_base_opts;
result.base_pipelines.push_back({ base_vs_mask, base_fs_mask });
for (const u32 vs_opt : vs_base_masks)
{
for (const u32 fs_opt : fs_base_masks)
{
result.base_pipelines.push_back({ vs_opt, fs_opt });
}
}
return result;
} }
} }

View File

@ -32,6 +32,11 @@ namespace program_common
// Meta // Meta
COMPILER_OPT_MAX = COMPILER_OPT_ENABLE_ALPHA_TEST_NE, COMPILER_OPT_MAX = COMPILER_OPT_ENABLE_ALPHA_TEST_NE,
COMPILER_OPT_ALPHA_TEST_MASK = (0b111111 << 9), COMPILER_OPT_ALPHA_TEST_MASK = (0b111111 << 9),
COMPILER_OPT_ALL_VS_MASK = COMPILER_OPT_ENABLE_INSTANCING | COMPILER_OPT_ENABLE_VTX_TEXTURES,
COMPILER_OPT_BASE_FS_MASK = 0b1111111,
COMPILER_OPT_ALL_FS_MASK = COMPILER_OPT_BASE_FS_MASK | COMPILER_OPT_ALPHA_TEST_MASK,
COMPILER_OPT_VS_EXCL_MASK = COMPILER_OPT_ENABLE_INSTANCING,
COMPILER_OPT_FS_EXCL_MASK = COMPILER_OPT_ALPHA_TEST_MASK | COMPILER_OPT_ENABLE_STIPPLING | COMPILER_OPT_ENABLE_DEPTH_EXPORT | COMPILER_OPT_ENABLE_F32_EXPORT,
// Bounds // Bounds
COMPILER_OPT_FS_MAX = COMPILER_OPT_ENABLE_FLOW_CTRL, COMPILER_OPT_FS_MAX = COMPILER_OPT_ENABLE_FLOW_CTRL,
@ -56,7 +61,24 @@ namespace program_common
return s; return s;
} }
using interpreter_variant_t = std::pair<u32, u32>; struct interpreter_shader_variant_t
std::vector<interpreter_variant_t> get_interpreter_variants(); {
u32 shader_opt = 0;
u32 compatible_shader_opts = 0;
};
struct interpreter_pipeline_variant_t
{
interpreter_shader_variant_t vs_opts;
interpreter_shader_variant_t fs_opts;
};
struct interpreter_variants_t
{
std::vector<interpreter_pipeline_variant_t> pipelines;
std::vector<std::pair<u32, u32>> base_pipelines;
};
interpreter_variants_t get_interpreter_variants();
} }
} }

View File

@ -579,6 +579,7 @@ namespace vk
void shader_interpreter::preload(rsx::shader_loading_dialog* dlg) void shader_interpreter::preload(rsx::shader_loading_dialog* dlg)
{ {
#if 0
dlg->create("Precompiling interpreter variants.\nPlease wait...", "Shader Compilation"); dlg->create("Precompiling interpreter variants.\nPlease wait...", "Shader Compilation");
const auto variants = program_common::interpreter::get_interpreter_variants(); const auto variants = program_common::interpreter::get_interpreter_variants();
@ -589,13 +590,14 @@ namespace vk
u32 ctr = 0; u32 ctr = 0;
for (auto& variant : variants) for (auto& variant : variants)
{ {
build_fs(variant.first | variant.second); //build_fs(variant.first | variant.second);
build_vs(variant.first | variant.second); //build_vs(variant.first | variant.second);
dlg->update_msg(0, fmt::format("Building variant %u of %u...", ++ctr, limit)); dlg->update_msg(0, fmt::format("Building variant %u of %u...", ++ctr, limit));
dlg->inc_value(0, 1); dlg->inc_value(0, 1);
} }
dlg->inc_value(1, 1); dlg->inc_value(1, 1);
dlg->refresh(); dlg->refresh();
#endif
} }
}; };