diff options
-rw-r--r-- | src/compiler/Makefile.sources | 1 | ||||
-rw-r--r-- | src/compiler/nir/meson.build | 1 | ||||
-rw-r--r-- | src/compiler/nir/nir.h | 2 | ||||
-rw-r--r-- | src/compiler/nir/nir_builder.h | 25 | ||||
-rw-r--r-- | src/compiler/nir/nir_lower_alpha_test.c | 111 | ||||
-rw-r--r-- | src/compiler/shader_enums.h | 17 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_nir_lower_blend.c | 50 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_program.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir.h | 1 |
9 files changed, 168 insertions, 55 deletions
diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources index 36906f41dd5..352631a75ad 100644 --- a/src/compiler/Makefile.sources +++ b/src/compiler/Makefile.sources @@ -207,6 +207,7 @@ NIR_FILES = \ nir/nir_loop_analyze.c \ nir/nir_loop_analyze.h \ nir/nir_lower_64bit_packing.c \ + nir/nir_lower_alpha_test.c \ nir/nir_lower_alu_to_scalar.c \ nir/nir_lower_atomics.c \ nir/nir_lower_atomics_to_ssbo.c \ diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build index faa69e3aa30..144cf01d2c4 100644 --- a/src/compiler/nir/meson.build +++ b/src/compiler/nir/meson.build @@ -96,6 +96,7 @@ files_libnir = files( 'nir_loop_analyze.h', 'nir_lower_64bit_packing.c', 'nir_lower_alu_to_scalar.c', + 'nir_lower_alpha_test.c', 'nir_lower_atomics.c', 'nir_lower_atomics_to_ssbo.c', 'nir_lower_bitmap.c', diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index bb5aba605a1..5af150310f2 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -2447,6 +2447,8 @@ bool nir_lower_constant_initializers(nir_shader *shader, bool nir_move_vec_src_uses_to_dest(nir_shader *shader); bool nir_lower_vec_to_movs(nir_shader *shader); +void nir_lower_alpha_test(nir_shader *shader, enum compare_func func, + bool alpha_to_one); bool nir_lower_alu_to_scalar(nir_shader *shader); bool nir_lower_load_const_to_scalar(nir_shader *shader); bool nir_lower_read_invocation_to_scalar(nir_shader *shader); diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h index 7c65886356d..4bd5628ff7d 100644 --- a/src/compiler/nir/nir_builder.h +++ b/src/compiler/nir/nir_builder.h @@ -643,4 +643,29 @@ nir_jump(nir_builder *build, nir_jump_type jump_type) nir_builder_instr_insert(build, &jump->instr); } +static inline nir_ssa_def * +nir_compare_func(nir_builder *b, enum compare_func func, + nir_ssa_def *src0, nir_ssa_def *src1) +{ + switch (func) { + case COMPARE_FUNC_NEVER: + return nir_imm_int(b, 0); + case COMPARE_FUNC_ALWAYS: + return nir_imm_int(b, ~0); + case COMPARE_FUNC_EQUAL: + return nir_feq(b, src0, src1); + case COMPARE_FUNC_NOTEQUAL: + return nir_fne(b, src0, src1); + case COMPARE_FUNC_GREATER: + return nir_flt(b, src1, src0); + case COMPARE_FUNC_GEQUAL: + return nir_fge(b, src0, src1); + case COMPARE_FUNC_LESS: + return nir_flt(b, src0, src1); + case COMPARE_FUNC_LEQUAL: + return nir_fge(b, src1, src0); + } + unreachable("bad compare func"); +} + #endif /* NIR_BUILDER_H */ diff --git a/src/compiler/nir/nir_lower_alpha_test.c b/src/compiler/nir/nir_lower_alpha_test.c new file mode 100644 index 00000000000..bd433b8ec66 --- /dev/null +++ b/src/compiler/nir/nir_lower_alpha_test.c @@ -0,0 +1,111 @@ +/* + * Copyright © 2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * @file + * + * Implements GL alpha testing by comparing the output color's alpha to the + * alpha_ref intrinsic and emitting a discard based on it. + * + * The alpha_to_one value overrides the source alpha to 1.0 to implement + * GL_SAMPLE_ALPHA_TO_ONE, which applies before the alpha test (and would be + * rather silly to use with alpha test, but the spec permits). + */ + +#include "nir/nir.h" +#include "nir/nir_builder.h" + +void +nir_lower_alpha_test(nir_shader *shader, enum compare_func func, + bool alpha_to_one) +{ + assert(shader->stage == MESA_SHADER_FRAGMENT); + + nir_foreach_function(function, shader) { + nir_function_impl *impl = function->impl; + nir_builder b; + nir_builder_init(&b, impl); + b.cursor = nir_before_cf_list(&impl->body); + + nir_foreach_block(block, impl) { + nir_foreach_instr_safe(instr, block) { + if (instr->type == nir_instr_type_intrinsic) { + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + + nir_variable *out = NULL; + + switch (intr->intrinsic) { + case nir_intrinsic_store_var: + out = intr->variables[0]->var; + break; + case nir_intrinsic_store_output: + /* already had i/o lowered.. lookup the matching output var: */ + nir_foreach_variable(var, &shader->outputs) { + int drvloc = var->data.driver_location; + if (nir_intrinsic_base(intr) == drvloc) { + out = var; + break; + } + } + assume(out); + break; + default: + continue; + } + + if (out->data.mode != nir_var_shader_out) + continue; + + if (out->data.location != FRAG_RESULT_COLOR && + out->data.location != FRAG_RESULT_DATA0) + continue; + + b.cursor = nir_before_instr(&intr->instr); + + nir_ssa_def *alpha; + if (alpha_to_one) { + alpha = nir_imm_float(&b, 1.0); + } else { + alpha = nir_channel(&b, nir_ssa_for_src(&b, intr->src[0], 4), + 3); + } + + nir_ssa_def *condition = + nir_compare_func(&b, func, + alpha, nir_load_alpha_ref_float(&b)); + + nir_intrinsic_instr *discard = + nir_intrinsic_instr_create(b.shader, + nir_intrinsic_discard_if); + discard->num_components = 1; + discard->src[0] = nir_src_for_ssa(nir_inot(&b, condition)); + nir_builder_instr_insert(&b, &discard->instr); + shader->info.fs.uses_discard = true; + } + } + } + + nir_metadata_preserve(impl, nir_metadata_block_index | + nir_metadata_dominance); + } +} diff --git a/src/compiler/shader_enums.h b/src/compiler/shader_enums.h index 2f20e68c5d6..9d229d4199e 100644 --- a/src/compiler/shader_enums.h +++ b/src/compiler/shader_enums.h @@ -670,6 +670,23 @@ enum gl_tess_spacing TESS_SPACING_FRACTIONAL_EVEN, }; +/** + * A compare function enum for use in compiler lowering passes. This is in + * the same order as GL's compare functions (shifted down by GL_NEVER), and is + * exactly the same as gallium's PIPE_FUNC_*. + */ +enum compare_func +{ + COMPARE_FUNC_NEVER, + COMPARE_FUNC_LESS, + COMPARE_FUNC_EQUAL, + COMPARE_FUNC_LEQUAL, + COMPARE_FUNC_GREATER, + COMPARE_FUNC_NOTEQUAL, + COMPARE_FUNC_GEQUAL, + COMPARE_FUNC_ALWAYS, +}; + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/gallium/drivers/vc4/vc4_nir_lower_blend.c b/src/gallium/drivers/vc4/vc4_nir_lower_blend.c index a28ebb5bb7c..60eccb4fc00 100644 --- a/src/gallium/drivers/vc4/vc4_nir_lower_blend.c +++ b/src/gallium/drivers/vc4/vc4_nir_lower_blend.c @@ -450,54 +450,6 @@ vc4_logicop(nir_builder *b, int logicop_func, } static nir_ssa_def * -vc4_nir_pipe_compare_func(nir_builder *b, int func, - nir_ssa_def *src0, nir_ssa_def *src1) -{ - switch (func) { - default: - fprintf(stderr, "Unknown compare func %d\n", func); - /* FALLTHROUGH */ - case PIPE_FUNC_NEVER: - return nir_imm_int(b, 0); - case PIPE_FUNC_ALWAYS: - return nir_imm_int(b, ~0); - case PIPE_FUNC_EQUAL: - return nir_feq(b, src0, src1); - case PIPE_FUNC_NOTEQUAL: - return nir_fne(b, src0, src1); - case PIPE_FUNC_GREATER: - return nir_flt(b, src1, src0); - case PIPE_FUNC_GEQUAL: - return nir_fge(b, src0, src1); - case PIPE_FUNC_LESS: - return nir_flt(b, src0, src1); - case PIPE_FUNC_LEQUAL: - return nir_fge(b, src1, src0); - } -} - -static void -vc4_nir_emit_alpha_test_discard(struct vc4_compile *c, nir_builder *b, - nir_ssa_def *alpha) -{ - if (!c->fs_key->alpha_test) - return; - - nir_ssa_def *condition = - vc4_nir_pipe_compare_func(b, c->fs_key->alpha_test_func, - alpha, - nir_load_alpha_ref_float(b)); - - nir_intrinsic_instr *discard = - nir_intrinsic_instr_create(b->shader, - nir_intrinsic_discard_if); - discard->num_components = 1; - discard->src[0] = nir_src_for_ssa(nir_inot(b, condition)); - nir_builder_instr_insert(b, &discard->instr); - c->s->info.fs.uses_discard = true; -} - -static nir_ssa_def * vc4_nir_swizzle_and_pack(struct vc4_compile *c, nir_builder *b, nir_ssa_def **colors) { @@ -537,8 +489,6 @@ vc4_nir_blend_pipeline(struct vc4_compile *c, nir_builder *b, nir_ssa_def *src, if (c->fs_key->sample_alpha_to_one && c->fs_key->msaa) src_color[3] = nir_imm_float(b, 1.0); - vc4_nir_emit_alpha_test_discard(c, b, src_color[3]); - nir_ssa_def *packed_color; if (srgb) { /* Unswizzle the destination color. */ diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index e93333d35e7..bf7424bf28a 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -2250,8 +2250,15 @@ vc4_shader_ntq(struct vc4_context *vc4, enum qstage stage, c->s = nir_shader_clone(c, key->shader_state->base.ir.nir); - if (stage == QSTAGE_FRAG) + if (stage == QSTAGE_FRAG) { + if (c->fs_key->alpha_test_func != COMPARE_FUNC_ALWAYS) { + NIR_PASS_V(c->s, nir_lower_alpha_test, + c->fs_key->alpha_test_func, + c->fs_key->sample_alpha_to_one && + c->fs_key->msaa); + } NIR_PASS_V(c->s, vc4_nir_lower_blend, c); + } struct nir_lower_tex_options tex_options = { /* We would need to implement txs, but we don't want the @@ -2748,10 +2755,10 @@ vc4_update_compiled_fs(struct vc4_context *vc4, uint8_t prim_mode) key->stencil_full_writemasks = vc4->zsa->stencil_uniforms[2] != 0; key->depth_enabled = (vc4->zsa->base.depth.enabled || key->stencil_enabled); - if (vc4->zsa->base.alpha.enabled) { - key->alpha_test = true; + if (vc4->zsa->base.alpha.enabled) key->alpha_test_func = vc4->zsa->base.alpha.func; - } + else + key->alpha_test_func = COMPARE_FUNC_ALWAYS; if (key->is_points) { key->point_sprite_mask = diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index 6469e51b051..90acaef2898 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -354,7 +354,6 @@ struct vc4_fs_key { bool stencil_full_writemasks; bool is_points; bool is_lines; - bool alpha_test; bool point_coord_upper_left; bool light_twoside; bool msaa; |