rsx/common/d3d12: Support non default alpha function

Fix After burner climax cloud effects.
This commit is contained in:
Vincent Lejeune 2016-02-06 19:54:12 +01:00
parent 9e3132c3fc
commit 837e06e85b
7 changed files with 60 additions and 3 deletions

View File

@ -106,7 +106,7 @@ bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, con
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.front_back_color_enabled != binary2.front_back_color_enabled || binary1.alpha_func != binary2.alpha_func)
return false;
const qword *instBuffer1 = (const qword*)binary1.addr;
const qword *instBuffer2 = (const qword*)binary2.addr;

View File

@ -209,7 +209,8 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + 256));
fill_scale_offset_data(mapped_buffer);
int is_alpha_tested = !!(rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]);
float alpha_ref = (float&)rsx::method_registers[NV4097_SET_ALPHA_REF];
u8 alpha_ref_raw = (u8)(rsx::method_registers[NV4097_SET_ALPHA_REF] & 0xFF);
float alpha_ref = alpha_ref_raw / 255.f;
memcpy((char*)mapped_buffer + 16 * sizeof(float), &is_alpha_tested, sizeof(int));
memcpy((char*)mapped_buffer + 17 * sizeof(float), &alpha_ref, sizeof(float));
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 256));

View File

@ -253,7 +253,30 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS)
}
// Shaders don't always output colors (for instance if they write to depth only)
if (!first_output_name.empty())
OS << " if (isAlphaTested && Out." << first_output_name << ".a <= alphaRef) discard;\n";
{
switch (m_prog.alpha_func)
{
case rsx::comparaison_function::equal:
OS << " if (isAlphaTested && Out." << first_output_name << ".a != alphaRef) discard;\n";
break;
case rsx::comparaison_function::not_equal:
OS << " if (isAlphaTested && Out." << first_output_name << ".a == alphaRef) discard;\n";
break;
case rsx::comparaison_function::less_or_equal:
OS << " if (isAlphaTested && Out." << first_output_name << ".a > alphaRef) discard;\n";
break;
case rsx::comparaison_function::less:
OS << " if (isAlphaTested && Out." << first_output_name << ".a >= alphaRef) discard;\n";
break;
case rsx::comparaison_function::greater:
OS << " if (isAlphaTested && Out." << first_output_name << ".a <= alphaRef) discard;\n";
break;
case rsx::comparaison_function::greater_or_equal:
OS << " if (isAlphaTested && Out." << first_output_name << ".a < alphaRef) discard;\n";
break;
}
}
OS << " return Out;" << std::endl;
OS << "}" << std::endl;
}

View File

@ -790,6 +790,22 @@ rsx::window_pixel_center rsx::to_window_pixel_center(u8 in)
throw EXCEPTION("Unknow window pixel center %x", in);
}
rsx::comparaison_function rsx::to_comparaison_function(u16 in)
{
switch (in)
{
case CELL_GCM_NEVER: return rsx::comparaison_function::never;
case CELL_GCM_LESS: return rsx::comparaison_function::less;
case CELL_GCM_EQUAL: return rsx::comparaison_function::equal;
case CELL_GCM_LEQUAL: return rsx::comparaison_function::less_or_equal;
case CELL_GCM_GREATER: return rsx::comparaison_function::greater;
case CELL_GCM_NOTEQUAL: return rsx::comparaison_function::not_equal;
case CELL_GCM_GEQUAL: return rsx::comparaison_function::greater_or_equal;
case CELL_GCM_ALWAYS: return rsx::comparaison_function::always;
}
throw EXCEPTION("Wrong comparaison function %x", in);
}
enum
{

View File

@ -127,6 +127,20 @@ namespace rsx
};
window_pixel_center to_window_pixel_center(u8 in);
enum class comparaison_function : u8
{
never,
less,
equal,
less_or_equal,
greater,
not_equal,
greater_or_equal,
always
};
comparaison_function to_comparaison_function(u16 in);
}
enum

View File

@ -220,6 +220,7 @@ struct RSXFragmentProgram
u32 offset;
u32 ctrl;
u16 unnormalized_coords;
rsx::comparaison_function alpha_func;
bool front_back_color_enabled : 1;
bool back_color_diffuse_output : 1;
bool back_color_specular_output : 1;

View File

@ -670,6 +670,7 @@ namespace rsx
result.front_back_color_enabled = !rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN];
result.back_color_diffuse_output = !!(rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK] & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
result.back_color_specular_output = !!(rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK] & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
result.alpha_func = to_comparaison_function(rsx::method_registers[NV4097_SET_ALPHA_FUNC]);
u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
result.origin_mode = rsx::to_window_origin((shader_window >> 12) & 0xF);
result.pixel_center_mode = rsx::to_window_pixel_center((shader_window >> 16) & 0xF);
@ -766,6 +767,7 @@ namespace rsx
method_registers[NV4097_SET_CONTEXT_DMA_REPORT] = CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT;
rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN] = true;
rsx::method_registers[NV4097_SET_ALPHA_FUNC] = CELL_GCM_ALWAYS;
// Reset vertex attrib array
for (int i = 0; i < limits::vertex_count; i++)