nir: Add alpha_to_coverage lowering pass
Importing this pass from fs_visitor::emit_alpha_to_coverage_workaround() in intel/compiler. v2 (Caio Marcelo de Oliveira Filho): - Track store output and sample mask instruction - Nest math insturction for more readability - Bail out early if no gl_SampleMask v3: (Caio Marcelo de Oliveira Filho): - Do math instructions after instruction block - Restructure code - Move pass under src/intel/compiler v4: (Caio Marcelo de Oliveira Filho): - Organize dither mask calculation Signed-off-by: Sagar Ghuge <sagar.ghuge@intel.com> Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
This commit is contained in:
parent
0e4bd261b1
commit
7ecfbd4f6d
|
@ -102,6 +102,7 @@ brw_nir_link_shaders(const struct brw_compiler *compiler,
|
|||
|
||||
bool brw_nir_lower_cs_intrinsics(nir_shader *nir,
|
||||
unsigned dispatch_width);
|
||||
void brw_nir_lower_alpha_to_coverage(nir_shader *shader);
|
||||
void brw_nir_lower_legacy_clipping(nir_shader *nir,
|
||||
int nr_userclip_plane_consts,
|
||||
struct brw_stage_prog_data *prog_data);
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "compiler/nir/nir_builder.h"
|
||||
#include "brw_nir.h"
|
||||
|
||||
/**
|
||||
* We need to compute alpha to coverage dithering manually in shader
|
||||
* and replace sample mask store with the bitwise-AND of sample mask and
|
||||
* alpha to coverage dithering.
|
||||
*
|
||||
* The following formula is used to compute final sample mask:
|
||||
* m = int(16.0 * clamp(src0_alpha, 0.0, 1.0))
|
||||
* dither_mask = 0x1111 * ((0xfea80 >> (m & ~3)) & 0xf) |
|
||||
* 0x0808 * (m & 2) | 0x0100 * (m & 1)
|
||||
* sample_mask = sample_mask & dither_mask
|
||||
*
|
||||
* It gives a number of ones proportional to the alpha for 2, 4, 8 or 16
|
||||
* least significant bits of the result:
|
||||
* 0.0000 0000000000000000
|
||||
* 0.0625 0000000100000000
|
||||
* 0.1250 0001000000010000
|
||||
* 0.1875 0001000100010000
|
||||
* 0.2500 1000100010001000
|
||||
* 0.3125 1000100110001000
|
||||
* 0.3750 1001100010011000
|
||||
* 0.4375 1001100110011000
|
||||
* 0.5000 1010101010101010
|
||||
* 0.5625 1010101110101010
|
||||
* 0.6250 1011101010111010
|
||||
* 0.6875 1011101110111010
|
||||
* 0.7500 1110111011101110
|
||||
* 0.8125 1110111111101110
|
||||
* 0.8750 1111111011111110
|
||||
* 0.9375 1111111111111110
|
||||
* 1.0000 1111111111111111
|
||||
*/
|
||||
static nir_ssa_def *
|
||||
build_dither_mask(nir_builder b, nir_intrinsic_instr *store_instr)
|
||||
{
|
||||
nir_ssa_def *alpha =
|
||||
nir_channel(&b, nir_ssa_for_src(&b, store_instr->src[0], 4), 3);
|
||||
|
||||
nir_ssa_def *m =
|
||||
nir_f2i32(&b, nir_fmul_imm(&b, nir_fsat(&b, alpha), 16.0));
|
||||
|
||||
nir_ssa_def *part_a =
|
||||
nir_iand(&b,
|
||||
nir_imm_int(&b, 0xf),
|
||||
nir_ushr(&b,
|
||||
nir_imm_int(&b, 0xfea80),
|
||||
nir_iand(&b, m, nir_imm_int(&b, ~3))));
|
||||
|
||||
nir_ssa_def *part_b = nir_iand(&b, m, nir_imm_int(&b, 2));
|
||||
|
||||
nir_ssa_def *part_c = nir_iand(&b, m, nir_imm_int(&b, 1));
|
||||
|
||||
return nir_ior(&b,
|
||||
nir_imul_imm(&b, part_a, 0x1111),
|
||||
nir_ior(&b,
|
||||
nir_imul_imm(&b, part_b, 0x0808),
|
||||
nir_imul_imm(&b, part_c, 0x0100)));
|
||||
}
|
||||
|
||||
void
|
||||
brw_nir_lower_alpha_to_coverage(nir_shader *shader)
|
||||
{
|
||||
assert(shader->info.stage == MESA_SHADER_FRAGMENT);
|
||||
|
||||
/* Bail out early if we don't have gl_SampleMask */
|
||||
bool is_sample_mask = false;
|
||||
nir_foreach_variable(var, &shader->outputs) {
|
||||
if (var->data.location == FRAG_RESULT_SAMPLE_MASK) {
|
||||
is_sample_mask = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_sample_mask)
|
||||
return;
|
||||
|
||||
nir_foreach_function(function, shader) {
|
||||
nir_function_impl *impl = function->impl;
|
||||
nir_builder b;
|
||||
nir_builder_init(&b, impl);
|
||||
|
||||
nir_foreach_block(block, impl) {
|
||||
nir_intrinsic_instr *sample_mask_instr = NULL;
|
||||
nir_intrinsic_instr *store_instr = NULL;
|
||||
|
||||
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_output:
|
||||
nir_foreach_variable(var, &shader->outputs) {
|
||||
int drvloc = var->data.driver_location;
|
||||
if (nir_intrinsic_base(intr) == drvloc) {
|
||||
out = var;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (out->data.mode != nir_var_shader_out)
|
||||
continue;
|
||||
|
||||
/* save gl_SampleMask instruction pointer */
|
||||
if (out->data.location == FRAG_RESULT_SAMPLE_MASK) {
|
||||
assert(!sample_mask_instr);
|
||||
sample_mask_instr = intr;
|
||||
}
|
||||
|
||||
/* save out_color[0] instruction pointer */
|
||||
if ((out->data.location == FRAG_RESULT_COLOR ||
|
||||
out->data.location == FRAG_RESULT_DATA0)) {
|
||||
nir_src *offset_src = nir_get_io_offset_src(intr);
|
||||
if (nir_src_is_const(*offset_src) && nir_src_as_uint(*offset_src) == 0) {
|
||||
assert(!store_instr);
|
||||
store_instr = intr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sample_mask_instr && store_instr) {
|
||||
b.cursor = nir_before_instr(&store_instr->instr);
|
||||
nir_ssa_def *dither_mask = build_dither_mask(b, store_instr);
|
||||
|
||||
/* Combine dither_mask and reorder gl_SampleMask store instruction
|
||||
* after render target 0 store instruction.
|
||||
*/
|
||||
nir_instr_remove(&sample_mask_instr->instr);
|
||||
dither_mask = nir_iand(&b, sample_mask_instr->src[0].ssa, dither_mask);
|
||||
nir_instr_insert_after(&store_instr->instr, &sample_mask_instr->instr);
|
||||
nir_instr_rewrite_src(&sample_mask_instr->instr,
|
||||
&sample_mask_instr->src[0],
|
||||
nir_src_for_ssa(dither_mask));
|
||||
}
|
||||
}
|
||||
nir_metadata_preserve(impl, nir_metadata_block_index |
|
||||
nir_metadata_dominance);
|
||||
}
|
||||
}
|
|
@ -78,6 +78,7 @@ libintel_compiler_files = files(
|
|||
'brw_nir_attribute_workarounds.c',
|
||||
'brw_nir_lower_conversions.c',
|
||||
'brw_nir_lower_cs_intrinsics.c',
|
||||
'brw_nir_lower_alpha_to_coverage.c',
|
||||
'brw_nir_lower_image_load_store.c',
|
||||
'brw_nir_lower_mem_access_bit_sizes.c',
|
||||
'brw_nir_opt_peephole_ffma.c',
|
||||
|
|
Loading…
Reference in New Issue