xref: /aosp_15_r20/external/mesa3d/src/mesa/main/ff_fragment_shader.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
4  * All Rights Reserved.
5  * Copyright 2009 VMware, Inc.  All Rights Reserved.
6  * Copyright © 2010-2011 Intel Corporation
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the
10  * "Software"), to deal in the Software without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sub license, and/or sell copies of the Software, and to
13  * permit persons to whom the Software is furnished to do so, subject to
14  * the following conditions:
15  *
16  * The above copyright notice and this permission notice (including the
17  * next paragraph) shall be included in all copies or substantial portions
18  * of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
24  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  *
28  **************************************************************************/
29 
30 #include "util/glheader.h"
31 #include "main/context.h"
32 
33 #include "main/macros.h"
34 #include "main/state.h"
35 #include "main/texenvprogram.h"
36 #include "main/texobj.h"
37 #include "program/program.h"
38 #include "program/prog_cache.h"
39 #include "program/prog_statevars.h"
40 #include "program/prog_to_nir.h"
41 #include "util/bitscan.h"
42 
43 #include "state_tracker/st_context.h"
44 #include "state_tracker/st_program.h"
45 #include "state_tracker/st_nir.h"
46 
47 #include "compiler/nir/nir_builder.h"
48 #include "compiler/nir/nir_builtin_builder.h"
49 
50 /*
51  * Note on texture units:
52  *
53  * The number of texture units supported by fixed-function fragment
54  * processing is MAX_TEXTURE_COORD_UNITS, not MAX_TEXTURE_IMAGE_UNITS.
55  * That's because there's a one-to-one correspondence between texture
56  * coordinates and samplers in fixed-function processing.
57  *
58  * Since fixed-function vertex processing is limited to MAX_TEXTURE_COORD_UNITS
59  * sets of texcoords, so is fixed-function fragment processing.
60  *
61  * We can safely use ctx->Const.MaxTextureUnits for loop bounds.
62  */
63 
64 
65 static GLboolean
texenv_doing_secondary_color(struct gl_context * ctx)66 texenv_doing_secondary_color(struct gl_context *ctx)
67 {
68    if (ctx->Light.Enabled &&
69        (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))
70       return GL_TRUE;
71 
72    if (ctx->Fog.ColorSumEnabled)
73       return GL_TRUE;
74 
75    return GL_FALSE;
76 }
77 
78 struct state_key {
79    GLuint nr_enabled_units:4;
80    GLuint separate_specular:1;
81    GLuint fog_mode:2;          /**< FOG_x */
82    GLuint inputs_available:12;
83    GLuint num_draw_buffers:4;
84 
85    /* NOTE: This array of structs must be last! (see "keySize" below) */
86    struct {
87       GLuint enabled:1;
88       GLuint source_index:4;   /**< TEXTURE_x_INDEX */
89       GLuint shadow:1;
90 
91       /***
92        * These are taken from struct gl_tex_env_combine_packed
93        * @{
94        */
95       GLuint ModeRGB:4;
96       GLuint ModeA:4;
97       GLuint ScaleShiftRGB:2;
98       GLuint ScaleShiftA:2;
99       GLuint NumArgsRGB:3;
100       GLuint NumArgsA:3;
101       struct gl_tex_env_argument ArgsRGB[MAX_COMBINER_TERMS];
102       struct gl_tex_env_argument ArgsA[MAX_COMBINER_TERMS];
103       /** @} */
104    } unit[MAX_TEXTURE_COORD_UNITS];
105 };
106 
107 
108 /**
109  * Do we need to clamp the results of the given texture env/combine mode?
110  * If the inputs to the mode are in [0,1] we don't always have to clamp
111  * the results.
112  */
113 static GLboolean
need_saturate(GLuint mode)114 need_saturate( GLuint mode )
115 {
116    switch (mode) {
117    case TEXENV_MODE_REPLACE:
118    case TEXENV_MODE_MODULATE:
119    case TEXENV_MODE_INTERPOLATE:
120       return GL_FALSE;
121    case TEXENV_MODE_ADD:
122    case TEXENV_MODE_ADD_SIGNED:
123    case TEXENV_MODE_SUBTRACT:
124    case TEXENV_MODE_DOT3_RGB:
125    case TEXENV_MODE_DOT3_RGB_EXT:
126    case TEXENV_MODE_DOT3_RGBA:
127    case TEXENV_MODE_DOT3_RGBA_EXT:
128    case TEXENV_MODE_MODULATE_ADD_ATI:
129    case TEXENV_MODE_MODULATE_SIGNED_ADD_ATI:
130    case TEXENV_MODE_MODULATE_SUBTRACT_ATI:
131    case TEXENV_MODE_ADD_PRODUCTS_NV:
132    case TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV:
133       return GL_TRUE;
134    default:
135       assert(0);
136       return GL_FALSE;
137    }
138 }
139 
140 #define VERT_BIT_TEX_ANY    (0xff << VERT_ATTRIB_TEX0)
141 
142 /**
143  * Identify all possible varying inputs.  The fragment program will
144  * never reference non-varying inputs, but will track them via state
145  * constants instead.
146  *
147  * This function figures out all the inputs that the fragment program
148  * has access to and filters input bitmask.
149  */
filter_fp_input_mask(GLbitfield fp_inputs,struct gl_context * ctx)150 static GLbitfield filter_fp_input_mask( GLbitfield fp_inputs,
151                                         struct gl_context *ctx )
152 {
153    if (ctx->VertexProgram._Overriden) {
154       /* Somebody's messing with the vertex program and we don't have
155        * a clue what's happening.  Assume that it could be producing
156        * all possible outputs.
157        */
158       return fp_inputs;
159    }
160 
161    if (ctx->RenderMode == GL_FEEDBACK) {
162       /* _NEW_RENDERMODE */
163       return fp_inputs & (VARYING_BIT_COL0 | VARYING_BIT_TEX0);
164    }
165 
166    /* _NEW_PROGRAM */
167    const GLboolean vertexShader =
168          ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] != NULL;
169    const GLboolean vertexProgram = _mesa_arb_vertex_program_enabled(ctx);
170 
171    if (!(vertexProgram || vertexShader)) {
172       /* Fixed function vertex logic */
173       GLbitfield possible_inputs = 0;
174 
175       GLbitfield varying_inputs = ctx->VertexProgram._VaryingInputs;
176       /* We only update ctx->VertexProgram._VaryingInputs when in VP_MODE_FF _VPMode */
177       assert(VP_MODE_FF == ctx->VertexProgram._VPMode);
178 
179       /* These get generated in the setup routine regardless of the
180        * vertex program:
181        */
182       /* _NEW_POINT */
183       if (ctx->Point.PointSprite) {
184          /* All texture varyings are possible to use */
185          possible_inputs = VARYING_BITS_TEX_ANY;
186       }
187       else {
188          const GLbitfield possible_tex_inputs =
189                ctx->Texture._TexGenEnabled |
190                ctx->Texture._TexMatEnabled |
191                ((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0);
192 
193          possible_inputs = (possible_tex_inputs << VARYING_SLOT_TEX0);
194       }
195 
196       /* First look at what values may be computed by the generated
197        * vertex program:
198        */
199       if (ctx->Light.Enabled) {
200          possible_inputs |= VARYING_BIT_COL0;
201 
202          if (texenv_doing_secondary_color(ctx))
203             possible_inputs |= VARYING_BIT_COL1;
204       }
205 
206       /* Then look at what might be varying as a result of enabled
207        * arrays, etc:
208        */
209       if (varying_inputs & VERT_BIT_COLOR0)
210          possible_inputs |= VARYING_BIT_COL0;
211       if (varying_inputs & VERT_BIT_COLOR1)
212          possible_inputs |= VARYING_BIT_COL1;
213 
214       return fp_inputs & possible_inputs;
215    }
216 
217    /* calculate from vp->outputs */
218    struct gl_program *vprog;
219 
220    /* Choose GLSL vertex shader over ARB vertex program.  Need this
221     * since vertex shader state validation comes after fragment state
222     * validation (see additional comments in state.c).
223     */
224    if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY] != NULL)
225       vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
226    else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] != NULL)
227       vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
228    else if (vertexShader)
229       vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
230    else
231       vprog = ctx->VertexProgram.Current;
232 
233    GLbitfield possible_inputs = vprog->info.outputs_written;
234 
235    /* These get generated in the setup routine regardless of the
236     * vertex program:
237     */
238    /* _NEW_POINT */
239    if (ctx->Point.PointSprite) {
240       /* All texture varyings are possible to use */
241       possible_inputs |= VARYING_BITS_TEX_ANY;
242    }
243 
244    return fp_inputs & possible_inputs;
245 }
246 
247 
248 /**
249  * Examine current texture environment state and generate a unique
250  * key to identify it.
251  */
make_state_key(struct gl_context * ctx,struct state_key * key)252 static GLuint make_state_key( struct gl_context *ctx,  struct state_key *key )
253 {
254    GLbitfield inputs_referenced = VARYING_BIT_COL0;
255    GLbitfield mask;
256    GLuint keySize;
257 
258    memset(key, 0, sizeof(*key));
259 
260    /* _NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE */
261    mask = ctx->Texture._EnabledCoordUnits;
262    int i = -1;
263    while (mask) {
264       i = u_bit_scan(&mask);
265       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
266       const struct gl_texture_object *texObj = texUnit->_Current;
267       const struct gl_tex_env_combine_packed *comb =
268          &ctx->Texture.FixedFuncUnit[i]._CurrentCombinePacked;
269 
270       if (!texObj)
271          continue;
272 
273       key->unit[i].enabled = 1;
274       inputs_referenced |= VARYING_BIT_TEX(i);
275 
276       key->unit[i].source_index = texObj->TargetIndex;
277 
278       const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, i);
279       if (samp->Attrib.CompareMode == GL_COMPARE_R_TO_TEXTURE) {
280          const GLenum format = _mesa_texture_base_format(texObj);
281          key->unit[i].shadow = (format == GL_DEPTH_COMPONENT ||
282                                 format == GL_DEPTH_STENCIL_EXT);
283       }
284 
285       key->unit[i].ModeRGB = comb->ModeRGB;
286       key->unit[i].ModeA = comb->ModeA;
287       key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB;
288       key->unit[i].ScaleShiftA = comb->ScaleShiftA;
289       key->unit[i].NumArgsRGB = comb->NumArgsRGB;
290       key->unit[i].NumArgsA = comb->NumArgsA;
291 
292       memcpy(key->unit[i].ArgsRGB, comb->ArgsRGB, sizeof comb->ArgsRGB);
293       memcpy(key->unit[i].ArgsA, comb->ArgsA, sizeof comb->ArgsA);
294    }
295 
296    key->nr_enabled_units = i + 1;
297 
298    /* _NEW_FOG */
299    if (texenv_doing_secondary_color(ctx)) {
300       key->separate_specular = 1;
301       inputs_referenced |= VARYING_BIT_COL1;
302    }
303 
304    /* _NEW_FOG */
305    key->fog_mode = ctx->Fog._PackedEnabledMode;
306 
307    /* _NEW_BUFFERS */
308    key->num_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
309 
310    /* _NEW_COLOR */
311    if (ctx->Color.AlphaEnabled && key->num_draw_buffers == 0) {
312       /* if alpha test is enabled we need to emit at least one color */
313       key->num_draw_buffers = 1;
314    }
315 
316    key->inputs_available = filter_fp_input_mask(inputs_referenced, ctx);
317 
318    /* compute size of state key, ignoring unused texture units */
319    keySize = sizeof(*key) - sizeof(key->unit)
320       + key->nr_enabled_units * sizeof(key->unit[0]);
321 
322    return keySize;
323 }
324 
325 
326 /** State used to build the fragment program:
327  */
328 struct texenv_fragment_program {
329    nir_builder *b;
330    struct gl_program_parameter_list *state_params;
331 
332    struct state_key *state;
333 
334    nir_variable *sampler_vars[MAX_TEXTURE_COORD_UNITS];
335 
336    nir_def *src_texture[MAX_TEXTURE_COORD_UNITS];
337    /* ssa-def containing each texture unit's sampled texture color,
338     * else NULL.
339     */
340 
341    nir_def *src_previous;   /**< Color from previous stage */
342 };
343 
344 static nir_variable *
register_state_var(struct texenv_fragment_program * p,gl_state_index s0,gl_state_index s1,gl_state_index s2,gl_state_index s3,const struct glsl_type * type)345 register_state_var(struct texenv_fragment_program *p,
346                    gl_state_index s0,
347                    gl_state_index s1,
348                    gl_state_index s2,
349                    gl_state_index s3,
350                    const struct glsl_type *type)
351 {
352    gl_state_index16 tokens[STATE_LENGTH];
353    tokens[0] = s0;
354    tokens[1] = s1;
355    tokens[2] = s2;
356    tokens[3] = s3;
357    nir_variable *var = nir_find_state_variable(p->b->shader, tokens);
358    if (var)
359       return var;
360 
361    int loc = _mesa_add_state_reference(p->state_params, tokens);
362 
363    char *name = _mesa_program_state_string(tokens);
364    var = nir_variable_create(p->b->shader, nir_var_uniform, type, name);
365    free(name);
366 
367    var->num_state_slots = 1;
368    var->state_slots = ralloc_array(var, nir_state_slot, 1);
369    var->data.driver_location = loc;
370    memcpy(var->state_slots[0].tokens, tokens,
371           sizeof(var->state_slots[0].tokens));
372 
373    p->b->shader->num_uniforms++;
374    return var;
375 }
376 
377 static nir_def *
load_state_var(struct texenv_fragment_program * p,gl_state_index s0,gl_state_index s1,gl_state_index s2,gl_state_index s3,const struct glsl_type * type)378 load_state_var(struct texenv_fragment_program *p,
379                gl_state_index s0,
380                gl_state_index s1,
381                gl_state_index s2,
382                gl_state_index s3,
383                const struct glsl_type *type)
384 {
385    nir_variable *var = register_state_var(p, s0, s1, s2, s3, type);
386    return nir_load_var(p->b, var);
387 }
388 
389 static nir_def *
load_input(struct texenv_fragment_program * p,gl_varying_slot slot,const struct glsl_type * type)390 load_input(struct texenv_fragment_program *p, gl_varying_slot slot,
391            const struct glsl_type *type)
392 {
393    nir_variable *var =
394       nir_get_variable_with_location(p->b->shader,
395                                      nir_var_shader_in,
396                                      slot,
397                                      type);
398    var->data.interpolation = INTERP_MODE_NONE;
399    return nir_load_var(p->b, var);
400 }
401 
402 static nir_def *
get_current_attrib(struct texenv_fragment_program * p,GLuint attrib)403 get_current_attrib(struct texenv_fragment_program *p, GLuint attrib)
404 {
405    return load_state_var(p, STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED,
406                          attrib, 0, 0,
407                          glsl_vec4_type());
408 }
409 
410 static nir_def *
get_gl_Color(struct texenv_fragment_program * p)411 get_gl_Color(struct texenv_fragment_program *p)
412 {
413    if (p->state->inputs_available & VARYING_BIT_COL0) {
414       return load_input(p, VARYING_SLOT_COL0, glsl_vec4_type());
415    } else {
416       return get_current_attrib(p, VERT_ATTRIB_COLOR0);
417    }
418 }
419 
420 static nir_def *
get_source(struct texenv_fragment_program * p,GLuint src,GLuint unit)421 get_source(struct texenv_fragment_program *p,
422            GLuint src, GLuint unit)
423 {
424    switch (src) {
425    case TEXENV_SRC_TEXTURE:
426       return p->src_texture[unit];
427 
428    case TEXENV_SRC_TEXTURE0:
429    case TEXENV_SRC_TEXTURE1:
430    case TEXENV_SRC_TEXTURE2:
431    case TEXENV_SRC_TEXTURE3:
432    case TEXENV_SRC_TEXTURE4:
433    case TEXENV_SRC_TEXTURE5:
434    case TEXENV_SRC_TEXTURE6:
435    case TEXENV_SRC_TEXTURE7:
436       return p->src_texture[src - TEXENV_SRC_TEXTURE0];
437 
438    case TEXENV_SRC_CONSTANT:
439       return load_state_var(p, STATE_TEXENV_COLOR,
440                             unit, 0, 0,
441                             glsl_vec4_type());
442 
443    case TEXENV_SRC_PRIMARY_COLOR:
444       return get_gl_Color(p);
445 
446    case TEXENV_SRC_ZERO:
447       return nir_imm_zero(p->b, 4, 32);
448 
449    case TEXENV_SRC_ONE:
450       return nir_imm_vec4(p->b, 1.0f, 1.0f, 1.0f, 1.0f);
451 
452    case TEXENV_SRC_PREVIOUS:
453       if (!p->src_previous) {
454          return get_gl_Color(p);
455       } else {
456          return p->src_previous;
457       }
458 
459    default:
460       assert(0);
461       return NULL;
462    }
463 }
464 
465 static nir_def *
emit_combine_source(struct texenv_fragment_program * p,GLuint unit,GLuint source,GLuint operand)466 emit_combine_source(struct texenv_fragment_program *p,
467                     GLuint unit,
468                     GLuint source,
469                     GLuint operand)
470 {
471    nir_def *src;
472 
473    src = get_source(p, source, unit);
474 
475    switch (operand) {
476    case TEXENV_OPR_ONE_MINUS_COLOR:
477       return nir_fsub_imm(p->b, 1.0, src);
478 
479    case TEXENV_OPR_ALPHA:
480       return src->num_components == 1 ? src : nir_channel(p->b, src, 3);
481 
482    case TEXENV_OPR_ONE_MINUS_ALPHA: {
483       nir_def *scalar =
484          src->num_components == 1 ? src : nir_channel(p->b, src, 3);
485 
486       return nir_fsub_imm(p->b, 1.0, scalar);
487    }
488 
489    case TEXENV_OPR_COLOR:
490       return src;
491 
492    default:
493       assert(0);
494       return src;
495    }
496 }
497 
498 /**
499  * Check if the RGB and Alpha sources and operands match for the given
500  * texture unit's combinder state.  When the RGB and A sources and
501  * operands match, we can emit fewer instructions.
502  */
args_match(const struct state_key * key,GLuint unit)503 static GLboolean args_match( const struct state_key *key, GLuint unit )
504 {
505    GLuint i, numArgs = key->unit[unit].NumArgsRGB;
506 
507    for (i = 0; i < numArgs; i++) {
508       if (key->unit[unit].ArgsA[i].Source != key->unit[unit].ArgsRGB[i].Source)
509          return GL_FALSE;
510 
511       switch (key->unit[unit].ArgsA[i].Operand) {
512       case TEXENV_OPR_ALPHA:
513          switch (key->unit[unit].ArgsRGB[i].Operand) {
514          case TEXENV_OPR_COLOR:
515          case TEXENV_OPR_ALPHA:
516             break;
517          default:
518             return GL_FALSE;
519          }
520          break;
521       case TEXENV_OPR_ONE_MINUS_ALPHA:
522          switch (key->unit[unit].ArgsRGB[i].Operand) {
523          case TEXENV_OPR_ONE_MINUS_COLOR:
524          case TEXENV_OPR_ONE_MINUS_ALPHA:
525             break;
526          default:
527             return GL_FALSE;
528          }
529          break;
530       default:
531          return GL_FALSE;        /* impossible */
532       }
533    }
534 
535    return GL_TRUE;
536 }
537 
538 static nir_def *
smear(nir_builder * b,nir_def * val)539 smear(nir_builder *b, nir_def *val)
540 {
541    if (val->num_components != 1)
542       return val;
543 
544    return nir_replicate(b, val, 4);
545 }
546 
547 static nir_def *
emit_combine(struct texenv_fragment_program * p,GLuint unit,GLuint nr,GLuint mode,const struct gl_tex_env_argument * opt)548 emit_combine(struct texenv_fragment_program *p,
549              GLuint unit,
550              GLuint nr,
551              GLuint mode,
552              const struct gl_tex_env_argument *opt)
553 {
554    nir_def *src[MAX_COMBINER_TERMS];
555    nir_def *tmp0, *tmp1;
556    GLuint i;
557 
558    assert(nr <= MAX_COMBINER_TERMS);
559 
560    for (i = 0; i < nr; i++)
561       src[i] = emit_combine_source( p, unit, opt[i].Source, opt[i].Operand );
562 
563    switch (mode) {
564    case TEXENV_MODE_REPLACE:
565       return src[0];
566 
567    case TEXENV_MODE_MODULATE:
568       return nir_fmul(p->b, src[0], src[1]);
569 
570    case TEXENV_MODE_ADD:
571       return nir_fadd(p->b, src[0], src[1]);
572 
573    case TEXENV_MODE_ADD_SIGNED:
574       return nir_fadd_imm(p->b, nir_fadd(p->b, src[0], src[1]), -0.5f);
575 
576    case TEXENV_MODE_INTERPOLATE:
577       return nir_flrp(p->b, src[1], src[0], src[2]);
578 
579    case TEXENV_MODE_SUBTRACT:
580       return nir_fsub(p->b, src[0], src[1]);
581 
582    case TEXENV_MODE_DOT3_RGBA:
583    case TEXENV_MODE_DOT3_RGBA_EXT:
584    case TEXENV_MODE_DOT3_RGB_EXT:
585    case TEXENV_MODE_DOT3_RGB:
586       tmp0 = nir_fadd_imm(p->b, nir_fmul_imm(p->b, src[0], 2.0f), -1.0f);
587       tmp1 = nir_fadd_imm(p->b, nir_fmul_imm(p->b, src[1], 2.0f), -1.0f);
588       return nir_fdot3(p->b, smear(p->b, tmp0), smear(p->b, tmp1));
589 
590    case TEXENV_MODE_MODULATE_ADD_ATI:
591       return nir_fmad(p->b, src[0], src[2], src[1]);
592 
593    case TEXENV_MODE_MODULATE_SIGNED_ADD_ATI:
594       return nir_fadd_imm(p->b,
595                           nir_fadd(p->b,
596                                    nir_fmul(p->b, src[0], src[2]),
597                                    src[1]),
598                           -0.5f);
599 
600    case TEXENV_MODE_MODULATE_SUBTRACT_ATI:
601       return nir_fsub(p->b, nir_fmul(p->b, src[0], src[2]), src[1]);
602 
603    case TEXENV_MODE_ADD_PRODUCTS_NV:
604       return nir_fadd(p->b, nir_fmul(p->b, src[0], src[1]),
605                             nir_fmul(p->b, src[2], src[3]));
606 
607    case TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV:
608       return nir_fadd_imm(p->b,
609                           nir_fadd(p->b,
610                                    nir_fmul(p->b, src[0], src[1]),
611                                    nir_fmul(p->b, src[2], src[3])),
612                           -0.5f);
613    default:
614       assert(0);
615       return src[0];
616    }
617 }
618 
619 /**
620  * Generate instructions for one texture unit's env/combiner mode.
621  */
622 static nir_def *
emit_texenv(struct texenv_fragment_program * p,GLuint unit)623 emit_texenv(struct texenv_fragment_program *p, GLuint unit)
624 {
625    const struct state_key *key = p->state;
626    GLboolean rgb_saturate, alpha_saturate;
627    GLuint rgb_shift, alpha_shift;
628 
629    if (!key->unit[unit].enabled) {
630       return get_source(p, TEXENV_SRC_PREVIOUS, 0);
631    }
632 
633    switch (key->unit[unit].ModeRGB) {
634    case TEXENV_MODE_DOT3_RGB_EXT:
635       alpha_shift = key->unit[unit].ScaleShiftA;
636       rgb_shift = 0;
637       break;
638    case TEXENV_MODE_DOT3_RGBA_EXT:
639       alpha_shift = 0;
640       rgb_shift = 0;
641       break;
642    default:
643       rgb_shift = key->unit[unit].ScaleShiftRGB;
644       alpha_shift = key->unit[unit].ScaleShiftA;
645       break;
646    }
647 
648    /* If we'll do rgb/alpha shifting don't saturate in emit_combine().
649     * We don't want to clamp twice.
650     */
651    if (rgb_shift)
652       rgb_saturate = GL_FALSE;  /* saturate after rgb shift */
653    else if (need_saturate(key->unit[unit].ModeRGB))
654       rgb_saturate = GL_TRUE;
655    else
656       rgb_saturate = GL_FALSE;
657 
658    if (alpha_shift)
659       alpha_saturate = GL_FALSE;  /* saturate after alpha shift */
660    else if (need_saturate(key->unit[unit].ModeA))
661       alpha_saturate = GL_TRUE;
662    else
663       alpha_saturate = GL_FALSE;
664 
665    nir_def *val;
666 
667    /* Emit the RGB and A combine ops
668     */
669    if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
670        args_match(key, unit)) {
671       val = emit_combine(p, unit,
672                          key->unit[unit].NumArgsRGB,
673                          key->unit[unit].ModeRGB,
674                          key->unit[unit].ArgsRGB);
675       val = smear(p->b, val);
676       if (rgb_saturate)
677          val = nir_fsat(p->b, val);
678    }
679    else if (key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA_EXT ||
680             key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA) {
681       val = emit_combine(p, unit,
682                          key->unit[unit].NumArgsRGB,
683                          key->unit[unit].ModeRGB,
684                          key->unit[unit].ArgsRGB);
685       val = smear(p->b, val);
686       if (rgb_saturate)
687          val = nir_fsat(p->b, val);
688    }
689    else {
690       /* Need to do something to stop from re-emitting identical
691        * argument calculations here:
692        */
693       val = emit_combine(p, unit,
694                          key->unit[unit].NumArgsRGB,
695                          key->unit[unit].ModeRGB,
696                          key->unit[unit].ArgsRGB);
697       val = smear(p->b, val);
698       if (rgb_saturate)
699          val = nir_fsat(p->b, val);
700       nir_def *rgb = val;
701 
702       val = emit_combine(p, unit,
703                          key->unit[unit].NumArgsA,
704                          key->unit[unit].ModeA,
705                          key->unit[unit].ArgsA);
706 
707       if (val->num_components != 1)
708          val = nir_channel(p->b, val, 3);
709 
710       if (alpha_saturate)
711          val = nir_fsat(p->b, val);
712       nir_def *a = val;
713 
714       val = nir_vector_insert_imm(p->b, rgb, a, 3);
715    }
716 
717    /* Deal with the final shift:
718     */
719    if (alpha_shift || rgb_shift) {
720       nir_def *shift;
721 
722       if (rgb_shift == alpha_shift) {
723          shift = nir_imm_float(p->b, (float)(1 << rgb_shift));
724       }
725       else {
726          shift = nir_imm_vec4(p->b,
727             (float)(1 << rgb_shift),
728             (float)(1 << rgb_shift),
729             (float)(1 << rgb_shift),
730             (float)(1 << alpha_shift));
731       }
732 
733       return nir_fsat(p->b, nir_fmul(p->b, val, shift));
734    }
735    else
736       return val;
737 }
738 
739 
740 /**
741  * Generate instruction for getting a texture source term.
742  */
743 static void
load_texture(struct texenv_fragment_program * p,GLuint unit)744 load_texture(struct texenv_fragment_program *p, GLuint unit)
745 {
746    if (p->src_texture[unit])
747       return;
748 
749    const GLuint texTarget = p->state->unit[unit].source_index;
750    nir_def *texcoord;
751 
752    if (!(p->state->inputs_available & (VARYING_BIT_TEX0 << unit))) {
753       texcoord = get_current_attrib(p, VERT_ATTRIB_TEX0 + unit);
754    } else {
755       texcoord = load_input(p,
756          VARYING_SLOT_TEX0 + unit,
757          glsl_vec4_type());
758    }
759 
760    if (!p->state->unit[unit].enabled) {
761       p->src_texture[unit] = nir_imm_zero(p->b, 4, 32);
762       return ;
763    }
764 
765    unsigned num_srcs = 4;
766    if (p->state->unit[unit].shadow)
767       num_srcs++;
768 
769    nir_tex_instr *tex = nir_tex_instr_create(p->b->shader, num_srcs);
770    tex->op = nir_texop_tex;
771    tex->dest_type = nir_type_float32;
772    tex->texture_index = unit;
773    tex->sampler_index = unit;
774 
775    tex->sampler_dim =
776       _mesa_texture_index_to_sampler_dim(texTarget,
777                                          &tex->is_array);
778 
779    tex->coord_components =
780       glsl_get_sampler_dim_coordinate_components(tex->sampler_dim);
781    if (tex->is_array)
782       tex->coord_components++;
783 
784    nir_variable *var = p->sampler_vars[unit];
785    if (!var) {
786       const struct glsl_type *sampler_type =
787          glsl_sampler_type(tex->sampler_dim,
788                            p->state->unit[unit].shadow,
789                            tex->is_array, GLSL_TYPE_FLOAT);
790 
791       var = nir_variable_create(p->b->shader, nir_var_uniform,
792                                 sampler_type,
793                                 ralloc_asprintf(p->b->shader,
794                                                 "sampler_%d", unit));
795       var->data.binding = unit;
796       var->data.explicit_binding = true;
797 
798       p->sampler_vars[unit] = var;
799    }
800 
801    nir_deref_instr *deref = nir_build_deref_var(p->b, var);
802    tex->src[0] = nir_tex_src_for_ssa(nir_tex_src_texture_deref,
803                                      &deref->def);
804    tex->src[1] = nir_tex_src_for_ssa(nir_tex_src_sampler_deref,
805                                      &deref->def);
806 
807    nir_def *src2 =
808       nir_channels(p->b, texcoord,
809                    nir_component_mask(tex->coord_components));
810    tex->src[2] = nir_tex_src_for_ssa(nir_tex_src_coord, src2);
811 
812    tex->src[3] = nir_tex_src_for_ssa(nir_tex_src_projector,
813                                      nir_channel(p->b, texcoord, 3));
814 
815    if (p->state->unit[unit].shadow) {
816       tex->is_shadow = true;
817       nir_def *src4 =
818          nir_channel(p->b, texcoord, tex->coord_components);
819       tex->src[4] = nir_tex_src_for_ssa(nir_tex_src_comparator, src4);
820    }
821 
822    nir_def_init(&tex->instr, &tex->def, 4, 32);
823    p->src_texture[unit] = &tex->def;
824 
825    nir_builder_instr_insert(p->b, &tex->instr);
826    BITSET_SET(p->b->shader->info.textures_used, unit);
827    BITSET_SET(p->b->shader->info.samplers_used, unit);
828 }
829 
830 static void
load_texenv_source(struct texenv_fragment_program * p,GLuint src,GLuint unit)831 load_texenv_source(struct texenv_fragment_program *p,
832                    GLuint src, GLuint unit)
833 {
834    switch (src) {
835    case TEXENV_SRC_TEXTURE:
836       load_texture(p, unit);
837       break;
838 
839    case TEXENV_SRC_TEXTURE0:
840    case TEXENV_SRC_TEXTURE1:
841    case TEXENV_SRC_TEXTURE2:
842    case TEXENV_SRC_TEXTURE3:
843    case TEXENV_SRC_TEXTURE4:
844    case TEXENV_SRC_TEXTURE5:
845    case TEXENV_SRC_TEXTURE6:
846    case TEXENV_SRC_TEXTURE7:
847       load_texture(p, src - TEXENV_SRC_TEXTURE0);
848       break;
849 
850    default:
851       /* not a texture src - do nothing */
852       break;
853    }
854 }
855 
856 
857 /**
858  * Generate instructions for loading all texture source terms.
859  */
860 static GLboolean
load_texunit_sources(struct texenv_fragment_program * p,GLuint unit)861 load_texunit_sources(struct texenv_fragment_program *p, GLuint unit)
862 {
863    const struct state_key *key = p->state;
864    GLuint i;
865 
866    for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
867       load_texenv_source( p, key->unit[unit].ArgsRGB[i].Source, unit );
868    }
869 
870    for (i = 0; i < key->unit[unit].NumArgsA; i++) {
871       load_texenv_source( p, key->unit[unit].ArgsA[i].Source, unit );
872    }
873 
874    return GL_TRUE;
875 }
876 
877 static void
emit_instructions(struct texenv_fragment_program * p)878 emit_instructions(struct texenv_fragment_program *p)
879 {
880    struct state_key *key = p->state;
881    GLuint unit;
882 
883    if (key->nr_enabled_units) {
884       /* First pass - to support texture_env_crossbar, first identify
885        * all referenced texture sources and emit texld instructions
886        * for each:
887        */
888       for (unit = 0; unit < key->nr_enabled_units; unit++)
889          if (key->unit[unit].enabled) {
890             load_texunit_sources(p, unit);
891          }
892 
893       /* Second pass - emit combine instructions to build final color:
894        */
895       for (unit = 0; unit < key->nr_enabled_units; unit++) {
896          if (key->unit[unit].enabled) {
897             p->src_previous = emit_texenv(p, unit);
898          }
899       }
900    }
901 
902    nir_def *cf = get_source(p, TEXENV_SRC_PREVIOUS, 0);
903 
904    if (key->separate_specular) {
905       nir_def *spec_result = cf;
906 
907       nir_def *secondary;
908       if (p->state->inputs_available & VARYING_BIT_COL1)
909          secondary = load_input(p, VARYING_SLOT_COL1, glsl_vec4_type());
910       else
911          secondary = get_current_attrib(p, VERT_ATTRIB_COLOR1);
912 
913       secondary = nir_vector_insert_imm(p->b, secondary,
914                                         nir_imm_zero(p->b, 1, 32), 3);
915       cf = nir_fadd(p->b, spec_result, secondary);
916    }
917 
918    const char *name =
919       gl_frag_result_name(FRAG_RESULT_COLOR);
920    nir_variable *var =
921       nir_variable_create(p->b->shader, nir_var_shader_out,
922                           glsl_vec4_type(), name);
923 
924    var->data.location = FRAG_RESULT_COLOR;
925    var->data.driver_location = p->b->shader->num_outputs++;
926 
927    p->b->shader->info.outputs_written |= BITFIELD64_BIT(FRAG_RESULT_COLOR);
928 
929    nir_store_var(p->b, var, cf, 0xf);
930 }
931 
932 /**
933  * Generate a new fragment program which implements the context's
934  * current texture env/combine mode.
935  */
936 static nir_shader *
create_new_program(struct state_key * key,struct gl_program * program,const nir_shader_compiler_options * options)937 create_new_program(struct state_key *key,
938                    struct gl_program *program,
939                    const nir_shader_compiler_options *options)
940 {
941    struct texenv_fragment_program p;
942 
943    memset(&p, 0, sizeof(p));
944    p.state = key;
945 
946    program->Parameters = _mesa_new_parameter_list();
947    p.state_params = _mesa_new_parameter_list();
948 
949    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
950                                                   options,
951                                                   "ff-fs");
952 
953    nir_shader *s = b.shader;
954 
955    s->info.separate_shader = true;
956    s->info.subgroup_size = SUBGROUP_SIZE_UNIFORM;
957 
958    p.b = &b;
959 
960    if (key->num_draw_buffers)
961       emit_instructions(&p);
962 
963    nir_validate_shader(b.shader, "after generating ff-vertex shader");
964 
965    if (key->fog_mode)
966       NIR_PASS(_, b.shader, st_nir_lower_fog, key->fog_mode, p.state_params);
967 
968    _mesa_add_separate_state_parameters(program, p.state_params);
969    _mesa_free_parameter_list(p.state_params);
970 
971    return s;
972 }
973 
974 /**
975  * Return a fragment program which implements the current
976  * fixed-function texture, fog and color-sum operations.
977  */
978 struct gl_program *
_mesa_get_fixed_func_fragment_program(struct gl_context * ctx)979 _mesa_get_fixed_func_fragment_program(struct gl_context *ctx)
980 {
981    struct gl_program *prog;
982    struct state_key key;
983    GLuint keySize;
984 
985    keySize = make_state_key(ctx, &key);
986 
987    prog = (struct gl_program *)
988       _mesa_search_program_cache(ctx->FragmentProgram.Cache,
989                                  &key, keySize);
990 
991    if (!prog) {
992       prog = ctx->Driver.NewProgram(ctx, MESA_SHADER_FRAGMENT, 0, false);
993       if (!prog)
994          return NULL;
995 
996       const struct nir_shader_compiler_options *options =
997          st_get_nir_compiler_options(ctx->st, MESA_SHADER_FRAGMENT);
998 
999       nir_shader *s =
1000          create_new_program(&key, prog, options);
1001 
1002       prog->state.type = PIPE_SHADER_IR_NIR;
1003       prog->nir = s;
1004 
1005       prog->SamplersUsed = s->info.samplers_used[0];
1006 
1007       /* default mapping from samplers to texture units */
1008       for (unsigned i = 0; i < MAX_SAMPLERS; i++)
1009          prog->SamplerUnits[i] = i;
1010 
1011       st_program_string_notify(ctx, GL_FRAGMENT_PROGRAM_ARB, prog);
1012 
1013       _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
1014                                  &key, keySize, prog);
1015    }
1016 
1017    return prog;
1018 }
1019