From 023ea3772dfcd81e6a5822a1812ff991d68cccd8 Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Thu, 23 Mar 2017 11:54:16 +0100 Subject: [PATCH] nir/lower_wpos_center: support adding sample position to fragment coordinate According to section 14.6 of the Vulkan specification: "When sample shading is enabled, the x and y components of FragCoord reflect the location of the sample corresponding to the shader invocation." So add a boolean parameter to the lowering pass to select this behavior when we need it. Reviewed-by: Jason Ekstrand --- src/compiler/nir/nir.h | 2 +- src/compiler/nir/nir_lower_wpos_center.c | 31 ++++++++++++++++++------ src/intel/vulkan/anv_pipeline.c | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index d032787a2a0..f88707a31a0 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -2518,7 +2518,7 @@ typedef struct nir_lower_wpos_ytransform_options { bool nir_lower_wpos_ytransform(nir_shader *shader, const nir_lower_wpos_ytransform_options *options); -bool nir_lower_wpos_center(nir_shader *shader); +bool nir_lower_wpos_center(nir_shader *shader, const bool for_sample_shading); typedef struct nir_lower_drawpixels_options { int texcoord_state_tokens[5]; diff --git a/src/compiler/nir/nir_lower_wpos_center.c b/src/compiler/nir/nir_lower_wpos_center.c index 5a70848eb88..478818d8d66 100644 --- a/src/compiler/nir/nir_lower_wpos_center.c +++ b/src/compiler/nir/nir_lower_wpos_center.c @@ -39,11 +39,14 @@ * hardware which provides an integer pixel center. Vulkan mandates that * the pixel center must be half-integer, and also that the coordinate * system's origin must be upper left. This means that there's no need - * for a uniform - we can always just add a constant. + * for a uniform - we can always just add a constant. In the case that + * sample shading is enabled, Vulkan expects FragCoord to include sample + * positions. */ static void -add_half_to_fragcoord(nir_builder *b, nir_intrinsic_instr *intr) +update_fragcoord(nir_builder *b, nir_intrinsic_instr *intr, + const bool for_sample_shading) { nir_ssa_def *wpos = &intr->dest.ssa; @@ -51,14 +54,27 @@ add_half_to_fragcoord(nir_builder *b, nir_intrinsic_instr *intr) b->cursor = nir_after_instr(&intr->instr); - wpos = nir_fadd(b, wpos, nir_imm_vec4(b, 0.5f, 0.5f, 0.0f, 0.0f)); + if (!for_sample_shading) { + wpos = nir_fadd(b, wpos, nir_imm_vec4(b, 0.5f, 0.5f, 0.0f, 0.0f)); + } else { + nir_ssa_def *spos = + nir_load_system_value(b, nir_intrinsic_load_sample_pos, 0); + + wpos = nir_fadd(b, wpos, + nir_vec4(b, + nir_channel(b, spos, 0), + nir_channel(b, spos, 1), + nir_imm_float(b, 0.0f), + nir_imm_float(b, 0.0f))); + } nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, nir_src_for_ssa(wpos), wpos->parent_instr); } static bool -lower_wpos_center_block(nir_builder *b, nir_block *block) +lower_wpos_center_block(nir_builder *b, nir_block *block, + const bool for_sample_shading) { bool progress = false; @@ -73,7 +89,7 @@ lower_wpos_center_block(nir_builder *b, nir_block *block) var->data.location == VARYING_SLOT_POS) { /* gl_FragCoord should not have array/struct derefs: */ assert(dvar->deref.child == NULL); - add_half_to_fragcoord(b, intr); + update_fragcoord(b, intr, for_sample_shading); progress = true; } } @@ -84,7 +100,7 @@ lower_wpos_center_block(nir_builder *b, nir_block *block) } bool -nir_lower_wpos_center(nir_shader *shader) +nir_lower_wpos_center(nir_shader *shader, const bool for_sample_shading) { bool progress = false; nir_builder b; @@ -96,7 +112,8 @@ nir_lower_wpos_center(nir_shader *shader) nir_builder_init(&b, function->impl); nir_foreach_block(block, function->impl) { - progress = lower_wpos_center_block(&b, block) || progress; + progress = lower_wpos_center_block(&b, block, for_sample_shading) || + progress; } nir_metadata_preserve(function->impl, nir_metadata_block_index | nir_metadata_dominance); diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 23274ef2a87..8ad2d485360 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -158,7 +158,7 @@ anv_shader_compile_to_nir(struct anv_device *device, nir_var_shader_in | nir_var_shader_out | nir_var_system_value); if (stage == MESA_SHADER_FRAGMENT) - NIR_PASS_V(nir, nir_lower_wpos_center); + NIR_PASS_V(nir, nir_lower_wpos_center, false); /* Now that we've deleted all but the main function, we can go ahead and * lower the rest of the constant initializers. -- 2.30.2