mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 23:11:25 +12:00
rsx: Make fragment state dynamic to reduce shader permutations
This commit is contained in:
parent
8358bda133
commit
f71f67c4ff
12 changed files with 161 additions and 145 deletions
|
@ -3,7 +3,7 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "GLFragmentProgram.h"
|
||||
|
||||
#include "../Common/ProgramStateCache.h"
|
||||
#include "GLCommonDecompiler.h"
|
||||
#include "../GCM.h"
|
||||
|
||||
|
@ -145,45 +145,16 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
|||
OS << " float fog_param1;\n";
|
||||
OS << " uint alpha_test;\n";
|
||||
OS << " float alpha_ref;\n";
|
||||
OS << " uint alpha_func;\n";
|
||||
OS << " uint fog_mode;\n";
|
||||
OS << " uint window_origin;\n";
|
||||
OS << " uint window_height;\n";
|
||||
OS << " vec4 texture_parameters[16];\n"; //sampling: x,y scaling and (unused) offsets data
|
||||
OS << "};\n";
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Note: It's not clear whether fog is computed per pixel or per vertex.
|
||||
// But it makes more sense to compute exp of interpoled value than to interpolate exp values.
|
||||
void insert_fog_declaration(std::stringstream & OS, rsx::fog_mode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case rsx::fog_mode::linear:
|
||||
OS << " vec4 fogc = vec4(fog_param1 * fog_c.x + (fog_param0 - 1.), fog_param1 * fog_c.x + (fog_param0 - 1.), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::exponential:
|
||||
OS << " vec4 fogc = vec4(11.084 * (fog_param1 * fog_c.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * fog_c.x + fog_param0 - 1.5)), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::exponential2:
|
||||
OS << " vec4 fogc = vec4(4.709 * (fog_param1 * fog_c.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * fog_c.x + fog_param0 - 1.5), 2.)), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::linear_abs:
|
||||
OS << " vec4 fogc = vec4(fog_param1 * abs(fog_c.x) + (fog_param0 - 1.), fog_param1 * abs(fog_c.x) + (fog_param0 - 1.), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::exponential_abs:
|
||||
OS << " vec4 fogc = vec4(11.084 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5)), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::exponential2_abs:
|
||||
OS << " vec4 fogc = vec4(4.709 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), 2.)), 0., 0.);\n";
|
||||
break;
|
||||
default:
|
||||
OS << " vec4 fogc = vec4(0.);\n";
|
||||
return;
|
||||
}
|
||||
|
||||
OS << " fogc.y = clamp(fogc.y, 0., 1.);\n";
|
||||
}
|
||||
|
||||
void insert_texture_scale(std::stringstream & OS, const RSXFragmentProgram& prog, int index)
|
||||
{
|
||||
std::string vec_type = "vec2";
|
||||
|
@ -223,6 +194,19 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
|
|||
{
|
||||
glsl::insert_glsl_legacy_function(OS, glsl::glsl_fragment_program);
|
||||
|
||||
//TODO: Generate input mask during parse stage to avoid this
|
||||
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
|
||||
{
|
||||
for (const ParamItem& PI : PT.items)
|
||||
{
|
||||
if (PI.name == "fogc")
|
||||
{
|
||||
glsl::insert_fog_declaration(OS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::set<std::string> output_values =
|
||||
{
|
||||
"r0", "r1", "r2", "r3", "r4",
|
||||
|
@ -241,6 +225,7 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
|
|||
}
|
||||
}
|
||||
|
||||
OS << "//FP_HASH=" << fmt::format("%llX", program_hash_util::fragment_program_hash()(m_prog)) << "\n";
|
||||
OS << "void fs_main(" << parameters << ")\n";
|
||||
OS << "{\n";
|
||||
|
||||
|
@ -261,11 +246,7 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
|
|||
|
||||
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
|
||||
OS << " vec4 wpos = gl_FragCoord;\n";
|
||||
|
||||
//Flip wpos in Y
|
||||
//We could optionally export wpos from the VS, but this is so much easier
|
||||
if (m_prog.origin_mode == rsx::window_origin::bottom)
|
||||
OS << " wpos.y = " << std::to_string(m_prog.height) << " - wpos.y;\n";
|
||||
OS << " if (window_origin != 0) wpos.y = window_height - wpos.y;\n";
|
||||
|
||||
for (const ParamType& PT : m_parr.params[PF_PARAM_UNIFORM])
|
||||
{
|
||||
|
@ -326,7 +307,7 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
|
|||
|
||||
if (PI.name == "fogc")
|
||||
{
|
||||
insert_fog_declaration(OS, m_prog.fog_equation);
|
||||
OS << " vec4 fogc = fetch_fog_value(fog_mode);\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +375,7 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
|
|||
}
|
||||
}
|
||||
|
||||
OS << make_comparison_test(m_prog.alpha_func, "alpha_test != 0 && ", first_output_name + ".a", "alpha_ref");
|
||||
OS << " if (alpha_test != 0 && !comparison_passes(" << first_output_name << ".a, alpha_ref, alpha_func)) discard;\n";
|
||||
}
|
||||
|
||||
OS << "}\n\n";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue