From f7d0c427becc72e2d238a49f1ef4c103e7d76a08 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Fri, 20 Mar 2015 20:12:27 -0700 Subject: [PATCH] Implementing alpha testing. --- src/xenia/gpu/gl4/command_processor.cc | 17 ++++++------ src/xenia/gpu/gl4/draw_batcher.h | 6 ++--- src/xenia/gpu/gl4/gl4_shader.cc | 36 +++++++++++++++++++------- src/xenia/gpu/trace_viewer_main.cc | 21 ++++++++++++--- 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/xenia/gpu/gl4/command_processor.cc b/src/xenia/gpu/gl4/command_processor.cc index bd9c10a60..d317f8cb6 100644 --- a/src/xenia/gpu/gl4/command_processor.cc +++ b/src/xenia/gpu/gl4/command_processor.cc @@ -1812,14 +1812,6 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateState() { bool mismatch = false; - // Alpha testing -- ALPHAREF, ALPHAFUNC, ALPHATESTENABLE - // Deprecated in GL, implemented in shader. - // if(ALPHATESTENABLE && frag_out.a [<=/ALPHAFUNC] ALPHAREF) discard; - uint32_t color_control = regs[XE_GPU_REG_RB_COLORCONTROL].u32; - draw_batcher_.set_alpha_test((color_control & 0x4) != 0, // ALPAHTESTENABLE - color_control & 0x3, // ALPHAFUNC - regs[XE_GPU_REG_RB_ALPHA_REF].f32); - #define CHECK_UPDATE_STATUS(status, mismatch, error_message) \ { \ if (status == UpdateStatus::kError) { \ @@ -2075,8 +2067,17 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateRasterizerState() { } CommandProcessor::UpdateStatus CommandProcessor::UpdateBlendState() { + auto& reg_file = *register_file_; auto& regs = update_blend_state_regs_; + // Alpha testing -- ALPHAREF, ALPHAFUNC, ALPHATESTENABLE + // Deprecated in GL, implemented in shader. + // if(ALPHATESTENABLE && frag_out.a [<=/ALPHAFUNC] ALPHAREF) discard; + uint32_t color_control = reg_file[XE_GPU_REG_RB_COLORCONTROL].u32; + draw_batcher_.set_alpha_test((color_control & 0x4) != 0, // ALPAHTESTENABLE + color_control & 0x3, // ALPHAFUNC + reg_file[XE_GPU_REG_RB_ALPHA_REF].f32); + bool dirty = false; dirty |= SetShadowRegister(regs.rb_blendcontrol[0], XE_GPU_REG_RB_BLENDCONTROL_0); diff --git a/src/xenia/gpu/gl4/draw_batcher.h b/src/xenia/gpu/gl4/draw_batcher.h index 2e64e12d8..99d9121fb 100644 --- a/src/xenia/gpu/gl4/draw_batcher.h +++ b/src/xenia/gpu/gl4/draw_batcher.h @@ -171,9 +171,9 @@ class DrawBatcher { // This must match GL4Shader's header. struct CommonHeader { - float4 window_scale; // sx,sy, ?, ? - float4 vtx_fmt; // - float4 alpha_test; // alpha test enable, func, ref, ? + float4 window_scale; // sx,sy, ?, ? + float4 vtx_fmt; // + float4 alpha_test; // alpha test enable, func, ref, ? // TODO(benvanik): pack tightly GLuint64 texture_samplers[32]; diff --git a/src/xenia/gpu/gl4/gl4_shader.cc b/src/xenia/gpu/gl4/gl4_shader.cc index e200ad4ce..3f255869e 100644 --- a/src/xenia/gpu/gl4/gl4_shader.cc +++ b/src/xenia/gpu/gl4/gl4_shader.cc @@ -245,16 +245,32 @@ bool GL4Shader::PreparePixelShader( } has_prepared_ = true; - std::string source = GetHeader() + - "layout(origin_upper_left) in vec4 gl_FragCoord;\n" - "layout(location = 0) flat in uint draw_id;\n" - "layout(location = 1) in VertexData vtx;\n" - "layout(location = 0) out vec4 oC[4];\n" - "void processFragment(const in StateData state);\n" - "void main() {\n" + - " const StateData state = states[draw_id];\n" - " processFragment(state);\n" - "}\n"; + std::string source = + GetHeader() + + "layout(origin_upper_left) in vec4 gl_FragCoord;\n" + "layout(location = 0) flat in uint draw_id;\n" + "layout(location = 1) in VertexData vtx;\n" + "layout(location = 0) out vec4 oC[4];\n" + "void processFragment(const in StateData state);\n" + "void applyAlphaTest(int alpha_func, float alpha_ref) {\n" + " switch (alpha_func) {\n" + " case 0: discard;\n" + " case 1: if (oC[0].a < alpha_ref) discard; break;\n" + " case 2: if (oC[0].a == alpha_ref) discard; break;\n" + " case 3: if (oC[0].a <= alpha_ref) discard; break;\n" + " case 4: if (oC[0].a > alpha_ref) discard; break;\n" + " case 5: if (oC[0].a != alpha_ref) discard; break;\n" + " case 6: if (oC[0].a >= alpha_ref) discard; break;\n" + " case 7: break;\n" + " };\n" + "}\n" + "void main() {\n" + + " const StateData state = states[draw_id];\n" + " processFragment(state);\n" + " if (state.alpha_test.x != 0.0) {\n" + " applyAlphaTest(int(state.alpha_test.y), state.alpha_test.z);\n" + " }\n" + "}\n"; std::string translated_source = shader_translator_.TranslatePixelShader(this, program_cntl); diff --git a/src/xenia/gpu/trace_viewer_main.cc b/src/xenia/gpu/trace_viewer_main.cc index 30d606744..a57ec1a01 100644 --- a/src/xenia/gpu/trace_viewer_main.cc +++ b/src/xenia/gpu/trace_viewer_main.cc @@ -1166,6 +1166,10 @@ void DrawTextureInfo(TracePlayer& player, const Shader::SamplerDesc& desc) { ImGui::Columns(1); } +static const char* kCompareFuncNames[] = { + "", "<", "==", "<=", ">", "!=", ">=", "", +}; + void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player, uint8_t* membase) { auto gs = static_cast(player.graphics_system()); @@ -1464,14 +1468,25 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player, blend_color.y, blend_color.z, blend_color.w); ImGui::SameLine(); ImGui::ColorButton(blend_color, true); + + // Alpha testing -- ALPHAREF, ALPHAFUNC, ALPHATESTENABLE + // if(ALPHATESTENABLE && frag_out.a [<=/ALPHAFUNC] ALPHAREF) discard; + uint32_t color_control = regs[XE_GPU_REG_RB_COLORCONTROL].u32; + if ((color_control & 0x4) != 0) { + ImGui::BulletText("Alpha Test: discard if %s %.2f", + kCompareFuncNames[color_control & 0x3], + regs[XE_GPU_REG_RB_ALPHA_REF].f32); + } else { + ImGui::PushStyleColor(ImGuiCol_Text, kColorIgnored); + ImGui::BulletText("Alpha Test: disabled"); + ImGui::PopStyleColor(); + } + ImGui::TreePop(); } if (ImGui::TreeNode("Depth-Stencil State")) { auto rb_depthcontrol = regs[XE_GPU_REG_RB_DEPTHCONTROL].u32; auto rb_stencilrefmask = regs[XE_GPU_REG_RB_STENCILREFMASK].u32; - static const char* kCompareFuncNames[] = { - "", "<", "==", "<=", ">", "!=", ">=", "", - }; if (rb_depthcontrol & 0x00000002) { ImGui::BulletText("Depth Test: enabled"); } else {