rsx/fp: Fragment program overhaul

- Separate TXB from TXL: They are completely different!
- Properly perform TMU emulation in the fragment shader. Implemens SRGB conversion and alphakill at the moment
- Properly perform ROP emulation in the fragment shader. Implements FRAMEBUFFER_SRGB. While support on the chip looks to be incomplete (and wierd), it does work
- Document some more bits in SHADER_CONTROL register
This commit is contained in:
kd-11 2018-03-23 14:47:03 +03:00
parent c6a2525c9b
commit 9fc1740608
12 changed files with 213 additions and 220 deletions

View file

@ -956,9 +956,9 @@ namespace rsx
//TODO: Properly support alpha-to-coverage and alpha-to-one behavior in shaders
auto fragment_alpha_func = rsx::method_registers.alpha_func();
auto alpha_ref = rsx::method_registers.alpha_ref() / 255.f;
auto is_alpha_tested = (u32)rsx::method_registers.alpha_test_enabled();
auto rop_control = (u32)rsx::method_registers.alpha_test_enabled();
if (rsx::method_registers.msaa_alpha_to_coverage_enabled() && !is_alpha_tested)
if (rsx::method_registers.msaa_alpha_to_coverage_enabled() && !rop_control)
{
if (rsx::method_registers.msaa_enabled() &&
rsx::method_registers.surface_antialias() != rsx::surface_antialiasing::center_1_sample)
@ -968,7 +968,7 @@ namespace rsx
//simulated using combined alpha blend and alpha test
fragment_alpha_func = rsx::comparison_function::greater;
alpha_ref = rsx::method_registers.msaa_sample_mask()? 0.25f : 0.f;
is_alpha_tested |= (1 << 4);
rop_control |= (1 << 4);
}
}
@ -977,6 +977,9 @@ namespace rsx
const u32 alpha_func = static_cast<u32>(fragment_alpha_func);
const u32 fog_mode = static_cast<u32>(rsx::method_registers.fog_equation());
rop_control |= (alpha_func << 16);
rop_control |= rsx::method_registers.framebuffer_srgb_enabled() ? 0x2 : 0;
// Generate wpos coeffecients
// wpos equation is now as follows:
// wpos.y = (frag_coord / resolution_scale) * ((window_origin!=top)?-1.: 1.) + ((window_origin!=top)? window_height : 0)
@ -990,8 +993,7 @@ namespace rsx
const f32 wpos_bias = (window_origin == rsx::window_origin::top) ? 0.f : window_height;
u32 *dst = static_cast<u32*>(buffer);
stream_vector(dst, (u32&)fog0, (u32&)fog1, is_alpha_tested, (u32&)alpha_ref);
stream_vector(dst, (u32&)fog0, (u32&)fog1, rop_control, (u32&)alpha_ref);
stream_vector(dst + 4, alpha_func, fog_mode, (u32&)wpos_scale, (u32&)wpos_bias);
size_t offset = 8;
@ -1518,9 +1520,6 @@ namespace rsx
result.texture_scale[i][0] = sampler_descriptors[i]->scale_x;
result.texture_scale[i][1] = sampler_descriptors[i]->scale_y;
result.texture_scale[i][2] = (f32)tex.remap(); //Debug value
result.texture_scale[i][3] = (f32)tex.format(); //Debug value
result.textures_alpha_kill[i] = 0;
result.textures_zfunc[i] = 0;
if (!tex.enabled())
{
@ -1528,16 +1527,17 @@ namespace rsx
}
else
{
u32 texture_control = 0;
texture_dimensions[i] = sampler_descriptors[i]->image_type;
if (tex.alpha_kill_enabled())
{
//alphakill can be ignored unless a valid comparison function is set
const rsx::comparison_function func = (rsx::comparison_function)tex.zfunc();
if (func < rsx::comparison_function::always && func > rsx::comparison_function::never)
if (func < rsx::comparison_function::always && func >= rsx::comparison_function::never)
{
result.textures_alpha_kill[i] = 1;
result.textures_zfunc[i] = (u8)func;
texture_control |= (1 << 4); //alphakill enable
texture_control |= ((u32)func << 5); //alphakill function
}
}
@ -1577,6 +1577,9 @@ namespace rsx
LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format);
}
}
texture_control |= tex.gamma();
result.texture_scale[i][3] = (f32)texture_control;
}
}