mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00: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,6 +3,80 @@
|
|||
|
||||
#include "ShaderParam.h"
|
||||
|
||||
namespace program_common
|
||||
{
|
||||
static void insert_compare_op(std::ostream& OS)
|
||||
{
|
||||
OS << "bool comparison_passes(float a, float b, uint func)\n";
|
||||
OS << "{\n";
|
||||
OS << " switch (func)\n";
|
||||
OS << " {\n";
|
||||
OS << " default:\n";
|
||||
OS << " case 0: return false; //never\n";
|
||||
OS << " case 1: return (a < b); //less\n";
|
||||
OS << " case 2: return (a == b); //equal\n";
|
||||
OS << " case 3: return (a <= b); //lequal\n";
|
||||
OS << " case 4: return (a > b); //greater\n";
|
||||
OS << " case 5: return (a != b); //nequal\n";
|
||||
OS << " case 6: return (a >= b); //gequal\n";
|
||||
OS << " case 7: return true; //always\n";
|
||||
OS << " }\n";
|
||||
OS << "}\n\n";
|
||||
}
|
||||
|
||||
static void insert_fog_declaration(std::ostream& OS, const std::string wide_vector_type, const std::string input_coord, bool declare = false)
|
||||
{
|
||||
std::string template_body;
|
||||
|
||||
if (!declare)
|
||||
template_body += "$T fetch_fog_value(uint mode)\n";
|
||||
else
|
||||
template_body += "$T fetch_fog_value(uint mode, $T $I)\n";
|
||||
|
||||
template_body += "{\n";
|
||||
template_body += " $T result = $T(0., 0., 0., 0.);\n";
|
||||
template_body += " switch(mode)\n";
|
||||
template_body += " {\n";
|
||||
template_body += " default:\n";
|
||||
template_body += " return result;\n";
|
||||
template_body += " case 0:\n";
|
||||
template_body += " //linear\n";
|
||||
template_body += " result = $T(fog_param1 * $I.x + (fog_param0 - 1.), fog_param1 * $I.x + (fog_param0 - 1.), 0., 0.);\n";
|
||||
template_body += " break;\n";
|
||||
template_body += " case 1:\n";
|
||||
template_body += " //exponential\n";
|
||||
template_body += " result = $T(11.084 * (fog_param1 * $I.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * $I.x + fog_param0 - 1.5)), 0., 0.);\n";
|
||||
template_body += " break;\n";
|
||||
template_body += " case 2:\n";
|
||||
template_body += " //exponential2\n";
|
||||
template_body += " result = $T(4.709 * (fog_param1 * $I.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * $I.x + fog_param0 - 1.5), 2.)), 0., 0.);\n";
|
||||
template_body += " break;\n";
|
||||
template_body += " case 3:\n";
|
||||
template_body += " //exponential_abs\n";
|
||||
template_body += " result = $T(11.084 * (fog_param1 * abs($I.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs($I.x) + fog_param0 - 1.5)), 0., 0.);\n";
|
||||
template_body += " break;\n";
|
||||
template_body += " case 4:\n";
|
||||
template_body += " //exponential2_abs\n";
|
||||
template_body += " result = $T(4.709 * (fog_param1 * abs($I.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs($I.x) + fog_param0 - 1.5), 2.)), 0., 0.);\n";
|
||||
template_body += " break;\n";
|
||||
template_body += " case 5:\n";
|
||||
template_body += " //linear_abs\n";
|
||||
template_body += " result = $T(fog_param1 * abs($I.x) + (fog_param0 - 1.), fog_param1 * abs($I.x) + (fog_param0 - 1.), 0., 0.);\n";
|
||||
template_body += " break;\n";
|
||||
template_body += " }\n";
|
||||
template_body += "\n";
|
||||
template_body += " result.y = clamp(result.y, 0., 1.);\n";
|
||||
template_body += " return result;\n";
|
||||
template_body += "}\n\n";
|
||||
|
||||
std::pair<std::string, std::string> replacements[] =
|
||||
{std::make_pair("$T", wide_vector_type),
|
||||
std::make_pair("$I", input_coord)};
|
||||
|
||||
OS << fmt::replace_all(template_body, replacements);
|
||||
}
|
||||
}
|
||||
|
||||
namespace glsl
|
||||
{
|
||||
enum program_domain
|
||||
|
@ -242,6 +316,8 @@ namespace glsl
|
|||
if (domain == glsl::program_domain::glsl_vertex_program)
|
||||
return;
|
||||
|
||||
program_common::insert_compare_op(OS);
|
||||
|
||||
//NOTE: After testing with GOW, the w component is either the original depth or wraps around to the x component
|
||||
//Since component.r == depth_value with some precision loss, just use the precise depth value for now (further testing needed)
|
||||
OS << "vec4 decodeLinearDepth(float depth_value)\n";
|
||||
|
@ -263,4 +339,9 @@ namespace glsl
|
|||
OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n";
|
||||
OS << "}\n\n";
|
||||
}
|
||||
|
||||
static void insert_fog_declaration(std::ostream& OS)
|
||||
{
|
||||
program_common::insert_fog_declaration(OS, "vec4", "fog_c");
|
||||
}
|
||||
}
|
|
@ -107,9 +107,8 @@ size_t fragment_program_hash::operator()(const RSXFragmentProgram& program) cons
|
|||
bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const
|
||||
{
|
||||
if (binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords ||
|
||||
binary1.height != binary2.height || binary1.origin_mode != binary2.origin_mode || binary1.pixel_center_mode != binary2.pixel_center_mode ||
|
||||
binary1.back_color_diffuse_output != binary2.back_color_diffuse_output || binary1.back_color_specular_output != binary2.back_color_specular_output ||
|
||||
binary1.front_back_color_enabled != binary2.front_back_color_enabled || binary1.alpha_func != binary2.alpha_func || binary1.fog_equation != binary2.fog_equation ||
|
||||
binary1.front_back_color_enabled != binary2.front_back_color_enabled ||
|
||||
binary1.shadow_textures != binary2.shadow_textures || binary1.redirected_textures != binary2.redirected_textures)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -124,6 +124,8 @@ void insert_d3d12_legacy_function(std::ostream& OS, bool is_fragment_program)
|
|||
if (!is_fragment_program)
|
||||
return;
|
||||
|
||||
program_common::insert_compare_op(OS);
|
||||
|
||||
OS << "uint packSnorm2x16(float2 val)";
|
||||
OS << "{\n";
|
||||
OS << " uint high_bits = round(clamp(val.x, -1., 1.) * 32767.);\n";
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Common/ShaderParam.h"
|
||||
#include "../Common/GLSLCommon.h"
|
||||
|
||||
std::string getFloatTypeNameImp(size_t elementCount);
|
||||
std::string getFunctionImp(FUNCTION f);
|
||||
|
|
|
@ -42,8 +42,12 @@ void D3D12FragmentDecompiler::insertHeader(std::stringstream & OS)
|
|||
OS << " float4 userClipFactor[2];\n";
|
||||
OS << " float fog_param0;\n";
|
||||
OS << " float fog_param1;\n";
|
||||
OS << " int isAlphaTested;\n";
|
||||
OS << " float alphaRef;\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 << " float4 texture_parameters[16];\n";
|
||||
OS << "};\n";
|
||||
}
|
||||
|
@ -151,38 +155,6 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
|
|||
|
||||
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 << " float4 fogc = float4(fog_param1 * In.fogc.x + (fog_param0 - 1.), fog_param1 * In.fogc.x + (fog_param0 - 1.), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::exponential:
|
||||
OS << " float4 fogc = float4(11.084 * (fog_param1 * In.fogc.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * In.fogc.x + fog_param0 - 1.5)), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::exponential2:
|
||||
OS << " float4 fogc = float4(4.709 * (fog_param1 * In.fogc.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * In.fogc.x + fog_param0 - 1.5), 2.)), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::linear_abs:
|
||||
OS << " float4 fogc = float4(fog_param1 * abs(In.fogc.x) + (fog_param0 - 1.), fog_param1 * abs(In.fogc.x) + (fog_param0 - 1.), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::exponential_abs:
|
||||
OS << " float4 fogc = float4(11.084 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5)), 0., 0.);\n";
|
||||
break;
|
||||
case rsx::fog_mode::exponential2_abs:
|
||||
OS << " float4 fogc = float4(4.709 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5), 2.)), 0., 0.);\n";
|
||||
break;
|
||||
default:
|
||||
OS << " float4 fogc = float4(0., 0., 0., 0.);\n";
|
||||
return;
|
||||
}
|
||||
|
||||
OS << " fogc.y = saturate(fogc.y);\n";
|
||||
}
|
||||
|
||||
std::string insert_texture_fetch(const RSXFragmentProgram& prog, int index)
|
||||
{
|
||||
std::string tex_name = "tex" + std::to_string(index) + ".Sample";
|
||||
|
@ -205,6 +177,18 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
|
|||
{
|
||||
insert_d3d12_legacy_function(OS, true);
|
||||
|
||||
for (const ParamType &PT : m_parr.params[PF_PARAM_IN])
|
||||
{
|
||||
for (const ParamItem &PI : PT.items)
|
||||
{
|
||||
if (PI.name == "fogc")
|
||||
{
|
||||
program_common::insert_fog_declaration(OS, "float4", "fogc", true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::set<std::string> output_value =
|
||||
{
|
||||
"r0", "r1", "r2", "r3", "r4",
|
||||
|
@ -231,7 +215,7 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
|
|||
}
|
||||
if (PI.name == "fogc")
|
||||
{
|
||||
insert_fog_declaration(OS, m_prog.fog_equation);
|
||||
OS << " float4 fogc = fetch_fog_value(fog_mode, In.fogc);\n";
|
||||
continue;
|
||||
}
|
||||
if (PI.name == "ssa")
|
||||
|
@ -239,10 +223,9 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
|
|||
OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";\n";
|
||||
}
|
||||
}
|
||||
// A bit unclean, but works.
|
||||
OS << " " << "float4 wpos = In.Position;\n";
|
||||
if (m_prog.origin_mode == rsx::window_origin::bottom)
|
||||
OS << " wpos.y = (" << std::to_string(m_prog.height) << " - wpos.y);\n";
|
||||
|
||||
OS << " float4 wpos = In.Position;\n";
|
||||
OS << " if (window_origin != 0) wpos.y = window_height - wpos.y;\n";
|
||||
OS << " float4 ssa = is_front_face ? float4(1., 1., 1., 1.) : float4(-1., -1., -1., -1.);\n";
|
||||
|
||||
// Declare output
|
||||
|
@ -363,7 +346,7 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS)
|
|||
}
|
||||
}
|
||||
|
||||
OS << make_comparison_test(m_prog.alpha_func, "isAlphaTested && ", "Out." + first_output_name + ".a", "alphaRef");
|
||||
OS << " if (alpha_test != 0 && !comparison_passes(Out." << first_output_name << ".a, alpha_ref, alpha_func)) discard;\n";
|
||||
|
||||
}
|
||||
OS << " return Out;\n";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -937,7 +937,7 @@ void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
|
|||
u32 fragment_constants_offset;
|
||||
|
||||
const u32 fragment_constants_size = (const u32)m_prog_buffer.get_fragment_constants_buffer_size(fragment_program);
|
||||
const u32 fragment_buffer_size = fragment_constants_size + (17 * 4 * sizeof(float));
|
||||
const u32 fragment_buffer_size = fragment_constants_size + (18 * 4 * sizeof(float));
|
||||
|
||||
if (manually_flush_ring_buffers)
|
||||
{
|
||||
|
|
|
@ -223,17 +223,12 @@ struct RSXFragmentProgram
|
|||
u16 unnormalized_coords;
|
||||
u16 redirected_textures;
|
||||
u16 shadow_textures;
|
||||
rsx::comparison_function alpha_func;
|
||||
bool front_back_color_enabled : 1;
|
||||
bool back_color_diffuse_output : 1;
|
||||
bool back_color_specular_output : 1;
|
||||
bool front_color_diffuse_output : 1;
|
||||
bool front_color_specular_output : 1;
|
||||
u32 texture_dimensions;
|
||||
rsx::window_origin origin_mode;
|
||||
rsx::window_pixel_center pixel_center_mode;
|
||||
rsx::fog_mode fog_equation;
|
||||
u16 height;
|
||||
|
||||
float texture_pitch_scale[16];
|
||||
u8 textures_alpha_kill[16];
|
||||
|
|
|
@ -598,17 +598,22 @@ namespace rsx
|
|||
|
||||
void thread::fill_fragment_state_buffer(void *buffer, const RSXFragmentProgram &fragment_program)
|
||||
{
|
||||
u32 *dst = static_cast<u32*>(buffer);
|
||||
|
||||
const u32 is_alpha_tested = rsx::method_registers.alpha_test_enabled();
|
||||
const float alpha_ref = rsx::method_registers.alpha_ref() / 255.f;
|
||||
const f32 fog0 = rsx::method_registers.fog_params_0();
|
||||
const f32 fog1 = rsx::method_registers.fog_params_1();
|
||||
const u32 alpha_func = static_cast<u32>(rsx::method_registers.alpha_func());
|
||||
const u32 fog_mode = static_cast<u32>(rsx::method_registers.fog_equation());
|
||||
const u32 window_origin = static_cast<u32>(rsx::method_registers.shader_window_origin());
|
||||
const u32 window_height = rsx::method_registers.shader_window_height();
|
||||
const float one = 1.f;
|
||||
|
||||
stream_vector(dst, (u32&)fog0, (u32&)fog1, is_alpha_tested, (u32&)alpha_ref);
|
||||
u32 *dst = static_cast<u32*>(buffer);
|
||||
|
||||
size_t offset = 4;
|
||||
stream_vector(dst, (u32&)fog0, (u32&)fog1, is_alpha_tested, (u32&)alpha_ref);
|
||||
stream_vector(dst + 4, alpha_func, fog_mode, window_origin, window_height);
|
||||
|
||||
size_t offset = 8;
|
||||
for (int index = 0; index < 16; ++index)
|
||||
{
|
||||
stream_vector(&dst[offset], (u32&)fragment_program.texture_pitch_scale[index], (u32&)one, 0U, 0U);
|
||||
|
@ -1097,11 +1102,6 @@ namespace rsx
|
|||
result.back_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
|
||||
result.front_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE);
|
||||
result.front_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR);
|
||||
result.alpha_func = rsx::method_registers.alpha_func();
|
||||
result.fog_equation = rsx::method_registers.fog_equation();
|
||||
result.origin_mode = rsx::method_registers.shader_window_origin();
|
||||
result.pixel_center_mode = rsx::method_registers.shader_window_pixel();
|
||||
result.height = rsx::method_registers.shader_window_height();
|
||||
result.redirected_textures = 0;
|
||||
result.shadow_textures = 0;
|
||||
|
||||
|
|
|
@ -164,6 +164,10 @@ void VKFragmentDecompilerThread::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";
|
||||
OS << "};\n";
|
||||
|
||||
|
@ -178,38 +182,6 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
|||
|
||||
namespace vk
|
||||
{
|
||||
// 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";
|
||||
}
|
||||
|
||||
std::string insert_texture_fetch(const RSXFragmentProgram& prog, int index)
|
||||
{
|
||||
std::string tex_name = "tex" + std::to_string(index);
|
||||
|
@ -231,6 +203,19 @@ void VKFragmentDecompilerThread::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",
|
||||
|
@ -269,11 +254,7 @@ void VKFragmentDecompilerThread::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";
|
||||
|
||||
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);
|
||||
|
||||
|
@ -323,7 +304,7 @@ void VKFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
|
|||
|
||||
if (PI.name == "fogc")
|
||||
{
|
||||
vk::insert_fog_declaration(OS, m_prog.fog_equation);
|
||||
OS << " vec4 fogc = fetch_fog_value(fog_mode);\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +372,7 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
|
|||
}
|
||||
}
|
||||
|
||||
OS << make_comparison_test(m_prog.alpha_func, "bool(alpha_test) && ", 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";
|
||||
|
|
|
@ -1842,7 +1842,7 @@ void VKGSRender::load_program(u32 vertex_count, u32 vertex_base)
|
|||
auto &fragment_program = current_fragment_program;
|
||||
|
||||
const size_t fragment_constants_sz = m_prog_buffer->get_fragment_constants_buffer_size(fragment_program);
|
||||
const size_t fragment_buffer_sz = fragment_constants_sz + (17 * 4 * sizeof(float));
|
||||
const size_t fragment_buffer_sz = fragment_constants_sz + (18 * 4 * sizeof(float));
|
||||
const size_t required_mem = 512 + 8192 + fragment_buffer_sz;
|
||||
|
||||
const size_t vertex_state_offset = m_uniform_buffer_ring_info.alloc<256>(required_mem);
|
||||
|
|
|
@ -409,11 +409,6 @@ namespace rsx
|
|||
fp.ctrl = data.fp_ctrl;
|
||||
fp.texture_dimensions = data.fp_texture_dimensions;
|
||||
fp.unnormalized_coords = data.fp_unnormalized_coords;
|
||||
fp.height = data.fp_height;
|
||||
fp.pixel_center_mode = (rsx::window_pixel_center)(data.fp_pixel_layout & 0x3);
|
||||
fp.origin_mode = (rsx::window_origin)((data.fp_pixel_layout >> 2) & 0x1);
|
||||
fp.alpha_func = (rsx::comparison_function)((data.fp_pixel_layout >> 3) & 0xF);
|
||||
fp.fog_equation = (rsx::fog_mode)((data.fp_pixel_layout >> 7) & 0xF);
|
||||
fp.front_back_color_enabled = (data.fp_lighting_flags & 0x1) != 0;
|
||||
fp.back_color_diffuse_output = ((data.fp_lighting_flags >> 1) & 0x1) != 0;
|
||||
fp.back_color_specular_output = ((data.fp_lighting_flags >> 2) & 0x1) != 0;
|
||||
|
@ -444,8 +439,6 @@ namespace rsx
|
|||
data_block.fp_ctrl = fp.ctrl;
|
||||
data_block.fp_texture_dimensions = fp.texture_dimensions;
|
||||
data_block.fp_unnormalized_coords = fp.unnormalized_coords;
|
||||
data_block.fp_height = fp.height;
|
||||
data_block.fp_pixel_layout = (u16)fp.pixel_center_mode | (u16)fp.origin_mode << 2 | (u16)fp.alpha_func << 3;
|
||||
data_block.fp_lighting_flags = (u16)fp.front_back_color_enabled | (u16)fp.back_color_diffuse_output << 1 |
|
||||
(u16)fp.back_color_specular_output << 2 | (u16)fp.front_color_diffuse_output << 3 | (u16)fp.front_color_specular_output << 4;
|
||||
data_block.fp_shadow_textures = fp.shadow_textures;
|
||||
|
|
Loading…
Add table
Reference in a new issue