From d94ebaf58072d7bca5f030a53a889e86fef2f770 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Thu, 16 Aug 2018 13:44:48 +0300 Subject: [PATCH] [D3D12] HLSL alphatest --- .../gpu/d3d12/d3d12_command_processor.cc | 35 +++++++++++++++++++ src/xenia/gpu/hlsl_shader_translator.cc | 23 ++++++++++-- src/xenia/gpu/hlsl_shader_translator.h | 7 +++- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 2e44d9fe7..bdfaee37e 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -1032,6 +1032,8 @@ void D3D12CommandProcessor::UpdateSystemConstantValues( uint32_t sq_program_cntl = regs[XE_GPU_REG_SQ_PROGRAM_CNTL].u32; uint32_t sq_context_misc = regs[XE_GPU_REG_SQ_CONTEXT_MISC].u32; uint32_t rb_surface_info = regs[XE_GPU_REG_RB_SURFACE_INFO].u32; + uint32_t rb_colorcontrol = regs[XE_GPU_REG_RB_COLORCONTROL].u32; + uint32_t rb_alpha_ref = regs[XE_GPU_REG_RB_ALPHA_REF].u32; bool dirty = false; @@ -1137,6 +1139,39 @@ void D3D12CommandProcessor::UpdateSystemConstantValues( system_constants_.ssaa_inv_scale[0] = ssaa_inv_scale_x; system_constants_.ssaa_inv_scale[1] = ssaa_inv_scale_y; + // Alpha test. + uint32_t alpha_test_enabled = (rb_colorcontrol & 0x8) ? 1 : 0; + dirty |= system_constants_.alpha_test_enabled != alpha_test_enabled; + system_constants_.alpha_test_enabled = alpha_test_enabled; + if (rb_colorcontrol & 0x8) { + uint32_t alpha_test_function = rb_colorcontrol & 0x7; + // 0: Never - fail in [-inf, +inf]. + // 1: Less - fail in [ref, +inf]. + // 2: Equal - pass in [ref, ref]. + // 3: Less or equal - pass in [-inf, ref]. + // 4: Greater - fail in [-inf, ref]. + // 5: Not equal - fail in [ref, ref]. + // 6: Greater or equal - pass in [ref, +inf]. + // 7: Always - pass in [-inf, +inf]. + uint32_t alpha_test_range_start = + (alpha_test_function == 1 || alpha_test_function == 2 || + alpha_test_function == 5 || alpha_test_function == 6) + ? rb_alpha_ref + : 0xFF800000u; + uint32_t alpha_test_range_end = + (alpha_test_function == 2 || alpha_test_function == 3 || + alpha_test_function == 4 || alpha_test_function == 5) + ? rb_alpha_ref + : 0x7F800000u; + uint32_t alpha_test_range_pass = (alpha_test_function & 0x2) ? 1 : 0; + dirty |= system_constants_.alpha_test_range[0] != alpha_test_range_start; + dirty |= system_constants_.alpha_test_range[1] != alpha_test_range_end; + dirty |= system_constants_.alpha_test_range_pass != alpha_test_range_pass; + system_constants_.alpha_test_range[0] = alpha_test_range_start; + system_constants_.alpha_test_range[1] = alpha_test_range_end; + system_constants_.alpha_test_range_pass = alpha_test_range_pass; + } + // Color output index mapping. for (uint32_t i = 0; i < 4; ++i) { dirty |= system_constants_.color_output_map[i] != diff --git a/src/xenia/gpu/hlsl_shader_translator.cc b/src/xenia/gpu/hlsl_shader_translator.cc index e5b854f28..8ed4afd56 100644 --- a/src/xenia/gpu/hlsl_shader_translator.cc +++ b/src/xenia/gpu/hlsl_shader_translator.cc @@ -177,6 +177,9 @@ std::vector HlslShaderTranslator::CompleteTranslation() { " float xe_pixel_half_pixel_offset;\n" " float2 xe_ssaa_inv_scale;\n" " uint xe_pixel_pos_reg;\n" + " bool xe_alpha_test_enabled;\n" + " float2 xe_alpha_test_range;\n" + " bool xe_alpha_test_range_pass;\n" " uint4 xe_color_output_map;\n" "};\n" "\n" @@ -382,15 +385,29 @@ std::vector HlslShaderTranslator::CompleteTranslation() { " xe_output.position.xyz * xe_ndc_scale +\n" " xe_ndc_offset * xe_output.position.www;\n"); } else if (is_pixel_shader()) { - // Remap guest color outputs to host render targets because null render - // target descriptors are broken. source.Append( + // Perform alpha test - check if the alpha is within the specified + // bounds (inclusively), fail or pass depending on comparison mode and + // on the results of the bound test. + " [branch] if (xe_alpha_test_enabled) {\n" + " bool xe_alpha_test_failed =\n" + " xe_color_output[0u].a >= xe_alpha_test_range.x &&\n" + " xe_color_output[0u].a <= xe_alpha_test_range.y;\n" + " [flatten] if (xe_alpha_test_range_pass) {\n" + " xe_alpha_test_failed = !xe_alpha_test_failed;\n" + " }\n" + " if (xe_alpha_test_failed) {\n" + " discard;\n" + " }\n" + " }\n" + // Remap guest color outputs to host render targets because null render + // target descriptors are broken. " xe_output.colors[0] = xe_color_output[xe_color_output_map.r];\n" " xe_output.colors[1] = xe_color_output[xe_color_output_map.g];\n" " xe_output.colors[2] = xe_color_output[xe_color_output_map.b];\n" " xe_output.colors[3] = xe_color_output[xe_color_output_map.a];\n"); } - // TODO(Triang3l): Window offset, half pixel offset, alpha test, gamma. + // TODO(Triang3l): Half pixel offset, alpha test, gamma. source.Append( " return xe_output;\n" "}\n"); diff --git a/src/xenia/gpu/hlsl_shader_translator.h b/src/xenia/gpu/hlsl_shader_translator.h index b0cd06c0b..5ca464757 100644 --- a/src/xenia/gpu/hlsl_shader_translator.h +++ b/src/xenia/gpu/hlsl_shader_translator.h @@ -37,8 +37,13 @@ class HlslShaderTranslator : public ShaderTranslator { // vec4 3 float ssaa_inv_scale[2]; uint32_t pixel_pos_reg; - uint32_t padding_3; + uint32_t alpha_test_enabled; // vec4 4 + // The range is floats as uints so it's easier to pass infinity. + uint32_t alpha_test_range[2]; + uint32_t alpha_test_range_pass; + uint32_t padding_4; + // vec4 5 uint32_t color_output_map[4]; };