X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_lower_wpos_ytransform.c;h=d0a694f889b955027c56ff41e163099a2e442a98;hb=606dff1b73fa9509e3a0b21970f02068a8d40219;hp=41f8554424688472141161eb64744fa8a43597dc;hpb=287f099db170132518b75142de8580fd252fde45;p=mesa.git diff --git a/src/compiler/nir/nir_lower_wpos_ytransform.c b/src/compiler/nir/nir_lower_wpos_ytransform.c index 41f85544246..d0a694f889b 100644 --- a/src/compiler/nir/nir_lower_wpos_ytransform.c +++ b/src/compiler/nir/nir_lower_wpos_ytransform.c @@ -61,7 +61,7 @@ get_transform(lower_wpos_ytransform_state *state) var->state_slots[0].swizzle = SWIZZLE_XYZW; memcpy(var->state_slots[0].tokens, state->options->state_tokens, sizeof(var->state_slots[0].tokens)); - + var->data.how_declared = nir_var_hidden; state->transform = var; } return nir_load_var(&state->b, state->transform); @@ -77,19 +77,18 @@ nir_cmp(nir_builder *b, nir_ssa_def *src0, nir_ssa_def *src1, nir_ssa_def *src2) /* see emit_wpos_adjustment() in st_mesa_to_tgsi.c */ static void emit_wpos_adjustment(lower_wpos_ytransform_state *state, - nir_intrinsic_instr *intr, - bool invert, float adjX, float adjY[2]) + nir_intrinsic_instr *intr, bool invert, + float adjX, float adjY[2]) { nir_builder *b = &state->b; - nir_variable *fragcoord = intr->variables[0]->var; nir_ssa_def *wpostrans, *wpos_temp, *wpos_temp_y, *wpos_input; assert(intr->dest.is_ssa); + wpos_input = &intr->dest.ssa; - b->cursor = nir_before_instr(&intr->instr); + b->cursor = nir_after_instr(&intr->instr); wpostrans = get_transform(state); - wpos_input = nir_load_var(b, fragcoord); /* First, apply the coordinate shift: */ if (adjX || adjY[0] || adjY[1]) { @@ -123,19 +122,15 @@ emit_wpos_adjustment(lower_wpos_ytransform_state *state, * inversion/identity, or the other way around if we're drawing to an FBO. */ if (invert) { - /* MAD wpos_temp.y, wpos_input, wpostrans.xxxx, wpostrans.yyyy - */ - wpos_temp_y = nir_ffma(b, - nir_channel(b, wpos_temp, 1), - nir_channel(b, wpostrans, 0), - nir_channel(b, wpostrans, 1)); + /* wpos_temp.y = wpos_input * wpostrans.xxxx + wpostrans.yyyy */ + wpos_temp_y = nir_fadd(b, nir_fmul(b, nir_channel(b, wpos_temp, 1), + nir_channel(b, wpostrans, 0)), + nir_channel(b, wpostrans, 1)); } else { - /* MAD wpos_temp.y, wpos_input, wpostrans.zzzz, wpostrans.wwww - */ - wpos_temp_y = nir_ffma(b, - nir_channel(b, wpos_temp, 1), - nir_channel(b, wpostrans, 2), - nir_channel(b, wpostrans, 3)); + /* wpos_temp.y = wpos_input * wpostrans.zzzz + wpostrans.wwww */ + wpos_temp_y = nir_fadd(b, nir_fmul(b, nir_channel(b, wpos_temp, 1), + nir_channel(b, wpostrans, 2)), + nir_channel(b, wpostrans, 3)); } wpos_temp = nir_vec4(b, @@ -144,14 +139,15 @@ emit_wpos_adjustment(lower_wpos_ytransform_state *state, nir_channel(b, wpos_temp, 2), nir_channel(b, wpos_temp, 3)); - nir_ssa_def_rewrite_uses(&intr->dest.ssa, nir_src_for_ssa(wpos_temp)); + nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, + nir_src_for_ssa(wpos_temp), + wpos_temp->parent_instr); } static void lower_fragcoord(lower_wpos_ytransform_state *state, nir_intrinsic_instr *intr) { const nir_lower_wpos_ytransform_options *options = state->options; - nir_variable *fragcoord = intr->variables[0]->var; float adjX = 0.0f; float adjY[2] = { 0.0f, 0.0f }; bool invert = false; @@ -163,7 +159,7 @@ lower_fragcoord(lower_wpos_ytransform_state *state, nir_intrinsic_instr *intr) * * The bias of the y-coordinate depends on whether y-inversion takes place * (adjY[1]) or not (adjY[0]), which is in turn dependent on whether we are - * drawing to an FBO (causes additional inversion), and whether the the pipe + * drawing to an FBO (causes additional inversion), and whether the pipe * driver origin and the requested origin differ (the latter condition is * stored in the 'invert' variable). * @@ -186,7 +182,7 @@ lower_fragcoord(lower_wpos_ytransform_state *state, nir_intrinsic_instr *intr) * u,h -> l,i: (99.5 + 0.5) * -1 + 100 = 0 */ - if (fragcoord->data.origin_upper_left) { + if (state->shader->info.fs.origin_upper_left) { /* Fragment shader wants origin in upper-left */ if (options->fs_coord_origin_upper_left) { /* the driver supports upper-left origin */ @@ -208,7 +204,7 @@ lower_fragcoord(lower_wpos_ytransform_state *state, nir_intrinsic_instr *intr) } } - if (fragcoord->data.pixel_center_integer) { + if (state->shader->info.fs.pixel_center_integer) { /* Fragment shader wants pixel center integer */ if (options->fs_coord_pixel_center_integer) { /* the driver supports pixel center integer */ @@ -236,6 +232,31 @@ lower_fragcoord(lower_wpos_ytransform_state *state, nir_intrinsic_instr *intr) emit_wpos_adjustment(state, intr, invert, adjX, adjY); } +static void +lower_load_pointcoord(lower_wpos_ytransform_state *state, + nir_intrinsic_instr *intr) +{ + nir_builder *b = &state->b; + b->cursor = nir_after_instr(&intr->instr); + + nir_ssa_def *pntc = &intr->dest.ssa; + nir_ssa_def *transform = get_transform(state); + nir_ssa_def *y = nir_channel(b, pntc, 1); + /* The offset is 1 if we're flipping, 0 otherwise. */ + nir_ssa_def *offset = nir_fmax(b, nir_channel(b, transform, 2), + nir_imm_float(b, 0.0)); + /* Flip the sign of y if we're flipping. */ + nir_ssa_def *scaled = nir_fmul(b, y, nir_channel(b, transform, 0)); + + /* Reassemble the vector. */ + nir_ssa_def *flipped_pntc = nir_vec2(b, + nir_channel(b, pntc, 0), + nir_fadd(b, offset, scaled)); + + nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, nir_src_for_ssa(flipped_pntc), + flipped_pntc->parent_instr); +} + /* turns 'fddy(p)' into 'fddy(fmul(p, transform.x))' */ static void lower_fddy(lower_wpos_ytransform_state *state, nir_alu_instr *fddy) @@ -257,30 +278,84 @@ lower_fddy(lower_wpos_ytransform_state *state, nir_alu_instr *fddy) fddy->src[0].swizzle[i] = MIN2(i, pt->num_components - 1); } -static bool +/* Multiply interp_deref_at_offset's offset by transform.x to flip it. */ +static void +lower_interp_deref_at_offset(lower_wpos_ytransform_state *state, + nir_intrinsic_instr *interp) +{ + nir_builder *b = &state->b; + nir_ssa_def *offset; + nir_ssa_def *flip_y; + + b->cursor = nir_before_instr(&interp->instr); + + offset = nir_ssa_for_src(b, interp->src[1], 2); + flip_y = nir_fmul(b, nir_channel(b, offset, 1), + nir_channel(b, get_transform(state), 0)); + nir_instr_rewrite_src(&interp->instr, &interp->src[1], + nir_src_for_ssa(nir_vec2(b, nir_channel(b, offset, 0), + flip_y))); +} + +static void +lower_load_sample_pos(lower_wpos_ytransform_state *state, + nir_intrinsic_instr *intr) +{ + nir_builder *b = &state->b; + b->cursor = nir_after_instr(&intr->instr); + + nir_ssa_def *pos = &intr->dest.ssa; + nir_ssa_def *scale = nir_channel(b, get_transform(state), 0); + nir_ssa_def *neg_scale = nir_channel(b, get_transform(state), 2); + /* Either y or 1-y for scale equal to 1 or -1 respectively. */ + nir_ssa_def *flipped_y = + nir_fadd(b, nir_fmax(b, neg_scale, nir_imm_float(b, 0.0)), + nir_fmul(b, nir_channel(b, pos, 1), scale)); + nir_ssa_def *flipped_pos = nir_vec2(b, nir_channel(b, pos, 0), flipped_y); + + nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, nir_src_for_ssa(flipped_pos), + flipped_pos->parent_instr); +} + +static void lower_wpos_ytransform_block(lower_wpos_ytransform_state *state, nir_block *block) { nir_foreach_instr_safe(instr, block) { if (instr->type == nir_instr_type_intrinsic) { nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); - if (intr->intrinsic == nir_intrinsic_load_var) { - nir_deref_var *dvar = intr->variables[0]; - nir_variable *var = dvar->var; - - if (strcmp(var->name, "gl_FragCoord") == 0) { - /* gl_FragCoord should not have array/struct deref's: */ - assert(dvar->deref.child == NULL); + if (intr->intrinsic == nir_intrinsic_load_deref) { + nir_deref_instr *deref = nir_src_as_deref(intr->src[0]); + nir_variable *var = nir_deref_instr_get_variable(deref); + + if ((var->data.mode == nir_var_shader_in && + var->data.location == VARYING_SLOT_POS) || + (var->data.mode == nir_var_system_value && + var->data.location == SYSTEM_VALUE_FRAG_COORD)) { + /* gl_FragCoord should not have array/struct derefs: */ lower_fragcoord(state, intr); + } else if (var->data.mode == nir_var_system_value && + var->data.location == SYSTEM_VALUE_SAMPLE_POS) { + lower_load_sample_pos(state, intr); + } else if (var->data.mode == nir_var_shader_in && + var->data.location == VARYING_SLOT_PNTC && + state->shader->options->lower_wpos_pntc) { + lower_load_pointcoord(state, intr); } + } else if (intr->intrinsic == nir_intrinsic_load_frag_coord) { + lower_fragcoord(state, intr); + } else if (intr->intrinsic == nir_intrinsic_load_sample_pos) { + lower_load_sample_pos(state, intr); + } else if (intr->intrinsic == nir_intrinsic_interp_deref_at_offset) { + lower_interp_deref_at_offset(state, intr); } } else if (instr->type == nir_instr_type_alu) { nir_alu_instr *alu = nir_instr_as_alu(instr); - if (alu->op == nir_op_fddy) + if (alu->op == nir_op_fddy || + alu->op == nir_op_fddy_fine || + alu->op == nir_op_fddy_coarse) lower_fddy(state, alu); } } - - return true; } static void @@ -304,7 +379,7 @@ nir_lower_wpos_ytransform(nir_shader *shader, .shader = shader, }; - assert(shader->stage == MESA_SHADER_FRAGMENT); + assert(shader->info.stage == MESA_SHADER_FRAGMENT); nir_foreach_function(function, shader) { if (function->impl)