diff options
Diffstat (limited to 'src/compiler')
-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 |
6 files changed, 157 insertions, 0 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 |