1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright (C) 2019 Collabora, Ltd.
3*61046927SAndroid Build Coastguard Worker * Copyright (C) 2019-2020 Collabora, Ltd.
4*61046927SAndroid Build Coastguard Worker *
5*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
6*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
7*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
8*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
10*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
11*61046927SAndroid Build Coastguard Worker *
12*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
13*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
14*61046927SAndroid Build Coastguard Worker * Software.
15*61046927SAndroid Build Coastguard Worker *
16*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*61046927SAndroid Build Coastguard Worker * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*61046927SAndroid Build Coastguard Worker * SOFTWARE.
23*61046927SAndroid Build Coastguard Worker *
24*61046927SAndroid Build Coastguard Worker * Authors (Collabora):
25*61046927SAndroid Build Coastguard Worker * Alyssa Rosenzweig <[email protected]>
26*61046927SAndroid Build Coastguard Worker */
27*61046927SAndroid Build Coastguard Worker
28*61046927SAndroid Build Coastguard Worker #include "compiler.h"
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker /* Derivatives in Midgard are implemented on the texture pipe, rather than the
31*61046927SAndroid Build Coastguard Worker * ALU pipe as suggested by NIR. The rationale is that normal texture
32*61046927SAndroid Build Coastguard Worker * instructions require (implicit) derivatives to be calculated anyway, so it
33*61046927SAndroid Build Coastguard Worker * makes sense to reuse the derivative logic. Thus, in addition to the usual
34*61046927SAndroid Build Coastguard Worker * texturing ops that calculate derivatives, there are two explicit texture ops
35*61046927SAndroid Build Coastguard Worker * dFdx/dFdy that perform differencing across helper invocations in either
36*61046927SAndroid Build Coastguard Worker * horizontal or vertical directions.
37*61046927SAndroid Build Coastguard Worker *
38*61046927SAndroid Build Coastguard Worker * One major caveat is that derivatives can only be calculated on up to a vec2
39*61046927SAndroid Build Coastguard Worker * at a time. This restriction presumably is to save some silicon, as 99% of
40*61046927SAndroid Build Coastguard Worker * derivatives will be vec2 (autocalculating mip levels of 2D texture
41*61046927SAndroid Build Coastguard Worker * coordinates). Admittedly I'm not sure why 3D textures can have their levels
42*61046927SAndroid Build Coastguard Worker * calculated automatically, umm... Pressing on.
43*61046927SAndroid Build Coastguard Worker *
44*61046927SAndroid Build Coastguard Worker * This caveat is handled in two steps. During the first pass (code
45*61046927SAndroid Build Coastguard Worker * generation), we generate texture ops 1:1 to the incoming NIR derivatives.
46*61046927SAndroid Build Coastguard Worker * This works for float/vec2 but not for vec3/vec4. A later lowering pass will
47*61046927SAndroid Build Coastguard Worker * scan for vec3/vec4 derivatives and lower (split) to multiple instructions.
48*61046927SAndroid Build Coastguard Worker * This pass is separated as we'll have to rewrite th e destination into a
49*61046927SAndroid Build Coastguard Worker * register (rather than SSA) and we'd rather do this after we have the whole
50*61046927SAndroid Build Coastguard Worker * IR in front of us to do it at once.
51*61046927SAndroid Build Coastguard Worker */
52*61046927SAndroid Build Coastguard Worker
53*61046927SAndroid Build Coastguard Worker static unsigned
mir_derivative_mode(nir_intrinsic_op op)54*61046927SAndroid Build Coastguard Worker mir_derivative_mode(nir_intrinsic_op op)
55*61046927SAndroid Build Coastguard Worker {
56*61046927SAndroid Build Coastguard Worker switch (op) {
57*61046927SAndroid Build Coastguard Worker case nir_intrinsic_ddx:
58*61046927SAndroid Build Coastguard Worker case nir_intrinsic_ddx_fine:
59*61046927SAndroid Build Coastguard Worker case nir_intrinsic_ddx_coarse:
60*61046927SAndroid Build Coastguard Worker return TEXTURE_DFDX;
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker case nir_intrinsic_ddy:
63*61046927SAndroid Build Coastguard Worker case nir_intrinsic_ddy_fine:
64*61046927SAndroid Build Coastguard Worker case nir_intrinsic_ddy_coarse:
65*61046927SAndroid Build Coastguard Worker return TEXTURE_DFDY;
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker default:
68*61046927SAndroid Build Coastguard Worker unreachable("Invalid derivative op");
69*61046927SAndroid Build Coastguard Worker }
70*61046927SAndroid Build Coastguard Worker }
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker /* Returns true if a texturing op computes derivatives either explicitly or
73*61046927SAndroid Build Coastguard Worker * implicitly */
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Worker bool
mir_op_computes_derivatives(gl_shader_stage stage,unsigned op)76*61046927SAndroid Build Coastguard Worker mir_op_computes_derivatives(gl_shader_stage stage, unsigned op)
77*61046927SAndroid Build Coastguard Worker {
78*61046927SAndroid Build Coastguard Worker /* Only fragment shaders may compute derivatives, but the sense of
79*61046927SAndroid Build Coastguard Worker * "normal" changes in vertex shaders on certain GPUs */
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker if (op == midgard_tex_op_normal && stage != MESA_SHADER_FRAGMENT)
82*61046927SAndroid Build Coastguard Worker return false;
83*61046927SAndroid Build Coastguard Worker
84*61046927SAndroid Build Coastguard Worker switch (op) {
85*61046927SAndroid Build Coastguard Worker case midgard_tex_op_normal:
86*61046927SAndroid Build Coastguard Worker case midgard_tex_op_derivative:
87*61046927SAndroid Build Coastguard Worker assert(stage == MESA_SHADER_FRAGMENT);
88*61046927SAndroid Build Coastguard Worker return true;
89*61046927SAndroid Build Coastguard Worker default:
90*61046927SAndroid Build Coastguard Worker return false;
91*61046927SAndroid Build Coastguard Worker }
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker
94*61046927SAndroid Build Coastguard Worker void
midgard_emit_derivatives(compiler_context * ctx,nir_intrinsic_instr * instr)95*61046927SAndroid Build Coastguard Worker midgard_emit_derivatives(compiler_context *ctx, nir_intrinsic_instr *instr)
96*61046927SAndroid Build Coastguard Worker {
97*61046927SAndroid Build Coastguard Worker /* Create texture instructions */
98*61046927SAndroid Build Coastguard Worker midgard_instruction ins = {
99*61046927SAndroid Build Coastguard Worker .type = TAG_TEXTURE_4,
100*61046927SAndroid Build Coastguard Worker .dest_type = nir_type_float32,
101*61046927SAndroid Build Coastguard Worker .src =
102*61046927SAndroid Build Coastguard Worker {
103*61046927SAndroid Build Coastguard Worker ~0,
104*61046927SAndroid Build Coastguard Worker nir_src_index(ctx, &instr->src[0]),
105*61046927SAndroid Build Coastguard Worker ~0,
106*61046927SAndroid Build Coastguard Worker ~0,
107*61046927SAndroid Build Coastguard Worker },
108*61046927SAndroid Build Coastguard Worker .swizzle = SWIZZLE_IDENTITY_4,
109*61046927SAndroid Build Coastguard Worker .src_types =
110*61046927SAndroid Build Coastguard Worker {
111*61046927SAndroid Build Coastguard Worker nir_type_float32,
112*61046927SAndroid Build Coastguard Worker nir_type_float32,
113*61046927SAndroid Build Coastguard Worker },
114*61046927SAndroid Build Coastguard Worker .op = midgard_tex_op_derivative,
115*61046927SAndroid Build Coastguard Worker .texture =
116*61046927SAndroid Build Coastguard Worker {
117*61046927SAndroid Build Coastguard Worker .mode = mir_derivative_mode(instr->intrinsic),
118*61046927SAndroid Build Coastguard Worker .format = 2,
119*61046927SAndroid Build Coastguard Worker .in_reg_full = 1,
120*61046927SAndroid Build Coastguard Worker .out_full = 1,
121*61046927SAndroid Build Coastguard Worker .sampler_type = MALI_SAMPLER_FLOAT,
122*61046927SAndroid Build Coastguard Worker },
123*61046927SAndroid Build Coastguard Worker };
124*61046927SAndroid Build Coastguard Worker
125*61046927SAndroid Build Coastguard Worker ins.dest = nir_def_index_with_mask(&instr->def, &ins.mask);
126*61046927SAndroid Build Coastguard Worker emit_mir_instruction(ctx, ins);
127*61046927SAndroid Build Coastguard Worker }
128*61046927SAndroid Build Coastguard Worker
129*61046927SAndroid Build Coastguard Worker void
midgard_lower_derivatives(compiler_context * ctx,midgard_block * block)130*61046927SAndroid Build Coastguard Worker midgard_lower_derivatives(compiler_context *ctx, midgard_block *block)
131*61046927SAndroid Build Coastguard Worker {
132*61046927SAndroid Build Coastguard Worker mir_foreach_instr_in_block_safe(block, ins) {
133*61046927SAndroid Build Coastguard Worker if (ins->type != TAG_TEXTURE_4)
134*61046927SAndroid Build Coastguard Worker continue;
135*61046927SAndroid Build Coastguard Worker if (ins->op != midgard_tex_op_derivative)
136*61046927SAndroid Build Coastguard Worker continue;
137*61046927SAndroid Build Coastguard Worker
138*61046927SAndroid Build Coastguard Worker /* Check if we need to split */
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker bool upper = ins->mask & 0b1100;
141*61046927SAndroid Build Coastguard Worker bool lower = ins->mask & 0b0011;
142*61046927SAndroid Build Coastguard Worker
143*61046927SAndroid Build Coastguard Worker if (!(upper && lower))
144*61046927SAndroid Build Coastguard Worker continue;
145*61046927SAndroid Build Coastguard Worker
146*61046927SAndroid Build Coastguard Worker /* Duplicate for dedicated upper instruction */
147*61046927SAndroid Build Coastguard Worker
148*61046927SAndroid Build Coastguard Worker midgard_instruction dup;
149*61046927SAndroid Build Coastguard Worker memcpy(&dup, ins, sizeof(dup));
150*61046927SAndroid Build Coastguard Worker
151*61046927SAndroid Build Coastguard Worker /* Fixup masks. Make original just lower and dupe just upper */
152*61046927SAndroid Build Coastguard Worker
153*61046927SAndroid Build Coastguard Worker ins->mask &= 0b0011;
154*61046927SAndroid Build Coastguard Worker dup.mask &= 0b1100;
155*61046927SAndroid Build Coastguard Worker
156*61046927SAndroid Build Coastguard Worker /* Fixup swizzles */
157*61046927SAndroid Build Coastguard Worker dup.swizzle[0][0] = dup.swizzle[0][1] = dup.swizzle[0][2] = COMPONENT_X;
158*61046927SAndroid Build Coastguard Worker dup.swizzle[0][3] = COMPONENT_Y;
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker dup.swizzle[1][0] = COMPONENT_Z;
161*61046927SAndroid Build Coastguard Worker dup.swizzle[1][1] = dup.swizzle[1][2] = dup.swizzle[1][3] = COMPONENT_W;
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker /* Insert the new instruction */
164*61046927SAndroid Build Coastguard Worker mir_insert_instruction_before(ctx, mir_next_op(ins), dup);
165*61046927SAndroid Build Coastguard Worker
166*61046927SAndroid Build Coastguard Worker /* We'll need both instructions to write to the same index, so
167*61046927SAndroid Build Coastguard Worker * rewrite to use a register */
168*61046927SAndroid Build Coastguard Worker
169*61046927SAndroid Build Coastguard Worker unsigned new = make_compiler_temp_reg(ctx);
170*61046927SAndroid Build Coastguard Worker mir_rewrite_index(ctx, ins->dest, new);
171*61046927SAndroid Build Coastguard Worker }
172*61046927SAndroid Build Coastguard Worker }
173