xref: /aosp_15_r20/external/mesa3d/src/mesa/main/ffvertex_prog.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 /**
29  * \file ffvertex_prog.c
30  *
31  * Create a vertex program to execute the current fixed function T&L pipeline.
32  * \author Keith Whitwell
33  */
34 
35 
36 #include "main/errors.h"
37 #include "util/glheader.h"
38 #include "main/mtypes.h"
39 #include "main/macros.h"
40 #include "main/enums.h"
41 #include "main/context.h"
42 #include "main/ffvertex_prog.h"
43 #include "program/program.h"
44 #include "program/prog_cache.h"
45 #include "program/prog_statevars.h"
46 #include "util/bitscan.h"
47 
48 #include "state_tracker/st_program.h"
49 #include "state_tracker/st_nir.h"
50 
51 #include "compiler/nir/nir_builder.h"
52 #include "compiler/nir/nir_builtin_builder.h"
53 
54 /** Max of number of lights and texture coord units */
55 #define NUM_UNITS MAX2(MAX_TEXTURE_COORD_UNITS, MAX_LIGHTS)
56 
57 struct state_key {
58    GLbitfield varying_vp_inputs;
59 
60    unsigned fragprog_inputs_read:12;
61 
62    unsigned light_color_material_mask:12;
63    unsigned light_global_enabled:1;
64    unsigned light_local_viewer:1;
65    unsigned light_twoside:1;
66    unsigned material_shininess_is_zero:1;
67    unsigned need_eye_coords:1;
68    unsigned normalize:1;
69    unsigned rescale_normals:1;
70 
71    unsigned fog_distance_mode:2;
72    unsigned separate_specular:1;
73    unsigned point_attenuated:1;
74 
75    struct {
76       unsigned char light_enabled:1;
77       unsigned char light_eyepos3_is_zero:1;
78       unsigned char light_spotcutoff_is_180:1;
79       unsigned char light_attenuated:1;
80       unsigned char texmat_enabled:1;
81       unsigned char coord_replace:1;
82       unsigned char texgen_enabled:1;
83       unsigned char texgen_mode0:4;
84       unsigned char texgen_mode1:4;
85       unsigned char texgen_mode2:4;
86       unsigned char texgen_mode3:4;
87    } unit[NUM_UNITS];
88 };
89 
90 
91 #define TXG_NONE           0
92 #define TXG_OBJ_LINEAR     1
93 #define TXG_EYE_LINEAR     2
94 #define TXG_SPHERE_MAP     3
95 #define TXG_REFLECTION_MAP 4
96 #define TXG_NORMAL_MAP     5
97 
translate_texgen(GLboolean enabled,GLenum mode)98 static GLuint translate_texgen( GLboolean enabled, GLenum mode )
99 {
100    if (!enabled)
101       return TXG_NONE;
102 
103    switch (mode) {
104    case GL_OBJECT_LINEAR: return TXG_OBJ_LINEAR;
105    case GL_EYE_LINEAR: return TXG_EYE_LINEAR;
106    case GL_SPHERE_MAP: return TXG_SPHERE_MAP;
107    case GL_REFLECTION_MAP_NV: return TXG_REFLECTION_MAP;
108    case GL_NORMAL_MAP_NV: return TXG_NORMAL_MAP;
109    default: return TXG_NONE;
110    }
111 }
112 
113 #define FDM_EYE_RADIAL    0
114 #define FDM_EYE_PLANE     1
115 #define FDM_EYE_PLANE_ABS 2
116 #define FDM_FROM_ARRAY    3
117 
translate_fog_distance_mode(GLenum source,GLenum mode)118 static GLuint translate_fog_distance_mode(GLenum source, GLenum mode)
119 {
120    if (source == GL_FRAGMENT_DEPTH_EXT) {
121       switch (mode) {
122       case GL_EYE_RADIAL_NV:
123          return FDM_EYE_RADIAL;
124       case GL_EYE_PLANE:
125          return FDM_EYE_PLANE;
126       default: /* shouldn't happen; fall through to a sensible default */
127       case GL_EYE_PLANE_ABSOLUTE_NV:
128          return FDM_EYE_PLANE_ABS;
129       }
130    } else {
131       return FDM_FROM_ARRAY;
132    }
133 }
134 
check_active_shininess(struct gl_context * ctx,const struct state_key * key,GLuint side)135 static GLboolean check_active_shininess( struct gl_context *ctx,
136                                          const struct state_key *key,
137                                          GLuint side )
138 {
139    GLuint attr = MAT_ATTRIB_FRONT_SHININESS + side;
140 
141    if ((key->varying_vp_inputs & VERT_BIT_COLOR0) &&
142        (key->light_color_material_mask & (1 << attr)))
143       return GL_TRUE;
144 
145    if (key->varying_vp_inputs & VERT_BIT_MAT(attr))
146       return GL_TRUE;
147 
148    if (ctx->Light.Material.Attrib[attr][0] != 0.0F)
149       return GL_TRUE;
150 
151    return GL_FALSE;
152 }
153 
154 
make_state_key(struct gl_context * ctx,struct state_key * key)155 static void make_state_key( struct gl_context *ctx, struct state_key *key )
156 {
157    const struct gl_program *fp = ctx->FragmentProgram._Current;
158    GLbitfield mask;
159 
160    memset(key, 0, sizeof(struct state_key));
161 
162    if (_mesa_hw_select_enabled(ctx)) {
163       /* GL_SELECT mode only need position calculation.
164        * glBegin/End use VERT_BIT_SELECT_RESULT_OFFSET for multi name stack in one draw.
165        * glDrawArrays may also be called without user shader, fallback to FF one.
166        */
167       key->varying_vp_inputs = ctx->VertexProgram._VaryingInputs &
168          (VERT_BIT_POS | VERT_BIT_SELECT_RESULT_OFFSET);
169       return;
170    }
171 
172    /* This now relies on texenvprogram.c being active:
173     */
174    assert(fp);
175 
176    key->need_eye_coords = ctx->_NeedEyeCoords;
177 
178    key->fragprog_inputs_read = fp->info.inputs_read;
179    key->varying_vp_inputs = ctx->VertexProgram._VaryingInputs;
180 
181    if (ctx->RenderMode == GL_FEEDBACK) {
182       /* make sure the vertprog emits color and tex0 */
183       key->fragprog_inputs_read |= (VARYING_BIT_COL0 | VARYING_BIT_TEX0);
184    }
185 
186    if (ctx->Light.Enabled) {
187       key->light_global_enabled = 1;
188 
189       if (ctx->Light.Model.LocalViewer)
190           key->light_local_viewer = 1;
191 
192       if (ctx->Light.Model.TwoSide)
193           key->light_twoside = 1;
194 
195       if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
196          key->separate_specular = 1;
197 
198       if (ctx->Light.ColorMaterialEnabled) {
199           key->light_color_material_mask = ctx->Light._ColorMaterialBitmask;
200       }
201 
202       mask = ctx->Light._EnabledLights;
203       while (mask) {
204          const int i = u_bit_scan(&mask);
205          struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
206 
207          key->unit[i].light_enabled = 1;
208 
209          if (lu->EyePosition[3] == 0.0F)
210             key->unit[i].light_eyepos3_is_zero = 1;
211 
212          if (lu->SpotCutoff == 180.0F)
213             key->unit[i].light_spotcutoff_is_180 = 1;
214 
215          if (lu->ConstantAttenuation != 1.0F ||
216              lu->LinearAttenuation != 0.0F ||
217              lu->QuadraticAttenuation != 0.0F)
218             key->unit[i].light_attenuated = 1;
219       }
220 
221       if (check_active_shininess(ctx, key, 0)) {
222          key->material_shininess_is_zero = 0;
223       }
224       else if (key->light_twoside &&
225                check_active_shininess(ctx, key, 1)) {
226          key->material_shininess_is_zero = 0;
227       }
228       else {
229          key->material_shininess_is_zero = 1;
230       }
231    }
232 
233    if (ctx->Transform.Normalize)
234       key->normalize = 1;
235 
236    if (ctx->Transform.RescaleNormals)
237       key->rescale_normals = 1;
238 
239    /* Only distinguish fog parameters if we actually need */
240    if (key->fragprog_inputs_read & VARYING_BIT_FOGC)
241       key->fog_distance_mode =
242          translate_fog_distance_mode(ctx->Fog.FogCoordinateSource,
243                                      ctx->Fog.FogDistanceMode);
244 
245    if (ctx->Point._Attenuated)
246       key->point_attenuated = 1;
247 
248    mask = ctx->Texture._EnabledCoordUnits | ctx->Texture._TexGenEnabled
249       | ctx->Texture._TexMatEnabled | ctx->Point.CoordReplace;
250    while (mask) {
251       const int i = u_bit_scan(&mask);
252       struct gl_fixedfunc_texture_unit *texUnit =
253          &ctx->Texture.FixedFuncUnit[i];
254 
255       if (ctx->Point.PointSprite)
256          if (ctx->Point.CoordReplace & (1u << i))
257             key->unit[i].coord_replace = 1;
258 
259       if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
260          key->unit[i].texmat_enabled = 1;
261 
262       if (texUnit->TexGenEnabled) {
263          key->unit[i].texgen_enabled = 1;
264 
265          key->unit[i].texgen_mode0 =
266             translate_texgen( texUnit->TexGenEnabled & (1<<0),
267                               texUnit->GenS.Mode );
268          key->unit[i].texgen_mode1 =
269             translate_texgen( texUnit->TexGenEnabled & (1<<1),
270                               texUnit->GenT.Mode );
271          key->unit[i].texgen_mode2 =
272             translate_texgen( texUnit->TexGenEnabled & (1<<2),
273                               texUnit->GenR.Mode );
274          key->unit[i].texgen_mode3 =
275             translate_texgen( texUnit->TexGenEnabled & (1<<3),
276                               texUnit->GenQ.Mode );
277       }
278    }
279 }
280 
281 struct tnl_program {
282    const struct state_key *state;
283    struct gl_program_parameter_list *state_params;
284    GLboolean mvp_with_dp4;
285 
286    nir_builder *b;
287 
288    nir_def *eye_position;
289    nir_def *eye_position_z;
290    nir_def *eye_position_normalized;
291    nir_def *transformed_normal;
292 
293    GLuint materials;
294    GLuint color_materials;
295 };
296 
297 static nir_variable *
register_state_var(struct tnl_program * p,gl_state_index16 s0,gl_state_index16 s1,gl_state_index16 s2,gl_state_index16 s3,const struct glsl_type * type)298 register_state_var(struct tnl_program *p,
299                    gl_state_index16 s0,
300                    gl_state_index16 s1,
301                    gl_state_index16 s2,
302                    gl_state_index16 s3,
303                    const struct glsl_type *type)
304 {
305    gl_state_index16 tokens[STATE_LENGTH];
306    tokens[0] = s0;
307    tokens[1] = s1;
308    tokens[2] = s2;
309    tokens[3] = s3;
310    nir_variable *var = nir_find_state_variable(p->b->shader, tokens);
311    if (var)
312       return var;
313 
314    var = st_nir_state_variable_create(p->b->shader, type, tokens);
315    var->data.driver_location = _mesa_add_state_reference(p->state_params, tokens);
316 
317    return var;
318 }
319 
320 static nir_def *
load_state_var(struct tnl_program * p,gl_state_index16 s0,gl_state_index16 s1,gl_state_index16 s2,gl_state_index16 s3,const struct glsl_type * type)321 load_state_var(struct tnl_program *p,
322                gl_state_index16 s0,
323                gl_state_index16 s1,
324                gl_state_index16 s2,
325                gl_state_index16 s3,
326                const struct glsl_type *type)
327 {
328    nir_variable *var = register_state_var(p, s0, s1, s2, s3, type);
329    return nir_load_var(p->b, var);
330 }
331 
332 static nir_def *
load_state_vec4(struct tnl_program * p,gl_state_index16 s0,gl_state_index16 s1,gl_state_index16 s2,gl_state_index16 s3)333 load_state_vec4(struct tnl_program *p,
334                 gl_state_index16 s0,
335                 gl_state_index16 s1,
336                 gl_state_index16 s2,
337                 gl_state_index16 s3)
338 {
339    return load_state_var(p, s0, s1, s2, s3, glsl_vec4_type());
340 }
341 
342 static void
load_state_mat4(struct tnl_program * p,nir_def * out[4],gl_state_index state_index,unsigned tex_index)343 load_state_mat4(struct tnl_program *p, nir_def *out[4],
344                 gl_state_index state_index, unsigned tex_index)
345 {
346    for (int i = 0; i < 4; ++i)
347       out[i] = load_state_vec4(p, state_index, tex_index, i, i);
348 }
349 
350 static nir_def *
load_input(struct tnl_program * p,gl_vert_attrib attr,const struct glsl_type * type)351 load_input(struct tnl_program *p, gl_vert_attrib attr,
352            const struct glsl_type *type)
353 {
354    if (p->state->varying_vp_inputs & VERT_BIT(attr)) {
355       nir_variable *var = nir_get_variable_with_location(p->b->shader, nir_var_shader_in,
356                                                          attr, type);
357       p->b->shader->info.inputs_read |= (uint64_t)VERT_BIT(attr);
358       return nir_load_var(p->b, var);
359    } else
360       return load_state_var(p, STATE_CURRENT_ATTRIB, attr, 0, 0, type);
361 }
362 
363 static nir_def *
load_input_vec4(struct tnl_program * p,gl_vert_attrib attr)364 load_input_vec4(struct tnl_program *p, gl_vert_attrib attr)
365 {
366    return load_input(p, attr, glsl_vec4_type());
367 }
368 
369 static nir_variable *
register_output(struct tnl_program * p,gl_varying_slot slot,const struct glsl_type * type)370 register_output(struct tnl_program *p, gl_varying_slot slot,
371                 const struct glsl_type *type)
372 {
373    nir_variable *var = nir_get_variable_with_location(p->b->shader, nir_var_shader_out,
374                                                       slot, type);
375    p->b->shader->info.outputs_written |= BITFIELD64_BIT(slot);
376    return var;
377 }
378 
379 static void
store_output_vec4_masked(struct tnl_program * p,gl_varying_slot slot,nir_def * value,unsigned mask)380 store_output_vec4_masked(struct tnl_program *p, gl_varying_slot slot,
381                          nir_def *value, unsigned mask)
382 {
383    assert(mask <= 0xf);
384    nir_variable *var = register_output(p, slot, glsl_vec4_type());
385    nir_store_var(p->b, var, value, mask);
386 }
387 
388 static void
store_output_vec4(struct tnl_program * p,gl_varying_slot slot,nir_def * value)389 store_output_vec4(struct tnl_program *p, gl_varying_slot slot,
390                   nir_def *value)
391 {
392    store_output_vec4_masked(p, slot, value, 0xf);
393 }
394 
395 static void
store_output_float(struct tnl_program * p,gl_varying_slot slot,nir_def * value)396 store_output_float(struct tnl_program *p, gl_varying_slot slot,
397                    nir_def *value)
398 {
399    nir_variable *var = register_output(p, slot, glsl_float_type());
400    nir_store_var(p->b, var, value, 0x1);
401 }
402 
403 
404 static nir_def *
emit_matrix_transform_vec4(nir_builder * b,nir_def * mat[4],nir_def * src)405 emit_matrix_transform_vec4(nir_builder *b,
406                            nir_def *mat[4],
407                            nir_def *src)
408 {
409    return nir_vec4(b,
410                    nir_fdot4(b, src, mat[0]),
411                    nir_fdot4(b, src, mat[1]),
412                    nir_fdot4(b, src, mat[2]),
413                    nir_fdot4(b, src, mat[3]));
414 }
415 
416 static nir_def *
emit_transpose_matrix_transform_vec4(nir_builder * b,nir_def * mat[4],nir_def * src)417 emit_transpose_matrix_transform_vec4(nir_builder *b,
418                                      nir_def *mat[4],
419                                      nir_def *src)
420 {
421    nir_def *result;
422    result = nir_fmul(b, nir_channel(b, src, 0), mat[0]);
423    result = nir_fmad(b, nir_channel(b, src, 1), mat[1], result);
424    result = nir_fmad(b, nir_channel(b, src, 2), mat[2], result);
425    result = nir_fmad(b, nir_channel(b, src, 3), mat[3], result);
426    return result;
427 }
428 
429 static nir_def *
emit_matrix_transform_vec3(nir_builder * b,nir_def * mat[3],nir_def * src)430 emit_matrix_transform_vec3(nir_builder *b,
431                            nir_def *mat[3],
432                            nir_def *src)
433 {
434    return nir_vec3(b,
435                    nir_fdot3(b, src, mat[0]),
436                    nir_fdot3(b, src, mat[1]),
437                    nir_fdot3(b, src, mat[2]));
438 }
439 
440 static nir_def *
emit_normalize_vec3(nir_builder * b,nir_def * src)441 emit_normalize_vec3(nir_builder *b, nir_def *src)
442 {
443    nir_def *tmp = nir_frsq(b, nir_fdot3(b, src, src));
444    return nir_fmul(b, src, tmp);
445 }
446 
447 static void
emit_passthrough(struct tnl_program * p,gl_vert_attrib attr,gl_varying_slot varying)448 emit_passthrough(struct tnl_program *p, gl_vert_attrib attr,
449                  gl_varying_slot varying)
450 {
451    nir_def *val = load_input_vec4(p, attr);
452    store_output_vec4(p, varying, val);
453 }
454 
455 static nir_def *
get_eye_position(struct tnl_program * p)456 get_eye_position(struct tnl_program *p)
457 {
458    if (!p->eye_position) {
459       nir_def *pos =
460          load_input_vec4(p, VERT_ATTRIB_POS);
461       if (p->mvp_with_dp4) {
462          nir_def *modelview[4];
463          load_state_mat4(p, modelview, STATE_MODELVIEW_MATRIX, 0);
464          p->eye_position =
465             emit_matrix_transform_vec4(p->b, modelview, pos);
466       } else {
467          nir_def *modelview[4];
468          load_state_mat4(p, modelview,
469                          STATE_MODELVIEW_MATRIX_TRANSPOSE, 0);
470          p->eye_position =
471             emit_transpose_matrix_transform_vec4(p->b, modelview, pos);
472       }
473    }
474 
475    return p->eye_position;
476 }
477 
478 static nir_def *
get_eye_position_z(struct tnl_program * p)479 get_eye_position_z(struct tnl_program *p)
480 {
481    return nir_channel(p->b, get_eye_position(p), 2);
482 }
483 
484 static nir_def *
get_eye_position_normalized(struct tnl_program * p)485 get_eye_position_normalized(struct tnl_program *p)
486 {
487    if (!p->eye_position_normalized) {
488       nir_def *eye = get_eye_position(p);
489       p->eye_position_normalized = emit_normalize_vec3(p->b, eye);
490    }
491 
492    return p->eye_position_normalized;
493 }
494 
495 static nir_def *
get_transformed_normal(struct tnl_program * p)496 get_transformed_normal(struct tnl_program *p)
497 {
498    if (!p->transformed_normal &&
499        !p->state->need_eye_coords &&
500        !p->state->normalize &&
501        !(p->state->need_eye_coords == p->state->rescale_normals)) {
502       p->transformed_normal =
503          load_input(p, VERT_ATTRIB_NORMAL,
504                     glsl_vector_type(GLSL_TYPE_FLOAT, 3));
505    } else if (!p->transformed_normal) {
506       nir_def *normal =
507          load_input(p, VERT_ATTRIB_NORMAL,
508                     glsl_vector_type(GLSL_TYPE_FLOAT, 3));
509 
510       if (p->state->need_eye_coords) {
511          nir_def *mvinv[4];
512          load_state_mat4(p, mvinv, STATE_MODELVIEW_MATRIX_INVTRANS, 0);
513          normal = emit_matrix_transform_vec3(p->b, mvinv, normal);
514       }
515 
516       /* Normalize/Rescale:
517        */
518       if (p->state->normalize)
519          normal = emit_normalize_vec3(p->b, normal);
520       else if (p->state->need_eye_coords == p->state->rescale_normals) {
521          nir_def *scale =
522             load_state_var(p, STATE_NORMAL_SCALE, 0, 0, 0,
523                            glsl_float_type());
524          normal = nir_fmul(p->b, normal, scale);
525       }
526 
527       p->transformed_normal = normal;
528    }
529 
530    return p->transformed_normal;
531 }
532 
material_attrib(GLuint side,GLuint property)533 static GLuint material_attrib( GLuint side, GLuint property )
534 {
535    switch (property) {
536    case STATE_AMBIENT:
537       return MAT_ATTRIB_FRONT_AMBIENT + side;
538    case STATE_DIFFUSE:
539       return MAT_ATTRIB_FRONT_DIFFUSE + side;
540    case STATE_SPECULAR:
541       return MAT_ATTRIB_FRONT_SPECULAR + side;
542    case STATE_EMISSION:
543       return MAT_ATTRIB_FRONT_EMISSION + side;
544    case STATE_SHININESS:
545       return MAT_ATTRIB_FRONT_SHININESS + side;
546    default:
547       unreachable("invalid value");
548    }
549 }
550 
551 
552 /**
553  * Get a bitmask of which material values vary on a per-vertex basis.
554  */
set_material_flags(struct tnl_program * p)555 static void set_material_flags( struct tnl_program *p )
556 {
557    p->color_materials = 0;
558    p->materials = 0;
559 
560    if (p->state->varying_vp_inputs & VERT_BIT_COLOR0) {
561       p->materials =
562          p->color_materials = p->state->light_color_material_mask;
563    }
564 
565    p->materials |= ((p->state->varying_vp_inputs & VERT_BIT_MAT_ALL)
566                     >> VERT_ATTRIB_MAT(0));
567 }
568 
569 
570 static nir_def *
get_material(struct tnl_program * p,GLuint side,GLuint property)571 get_material(struct tnl_program *p, GLuint side,
572              GLuint property)
573 {
574    GLuint attrib = material_attrib(side, property);
575 
576    if (p->color_materials & (1<<attrib))
577       return load_input_vec4(p, VERT_ATTRIB_COLOR0);
578    else if (p->materials & (1<<attrib)) {
579       /* Put material values in the GENERIC slots -- they are not used
580        * for anything in fixed function mode.
581        */
582       return load_input_vec4(p, VERT_ATTRIB_MAT(attrib));
583    } else {
584       return load_state_vec4(p, STATE_MATERIAL, attrib, 0, 0);
585    }
586 }
587 
588 #define SCENE_COLOR_BITS(side) (( MAT_BIT_FRONT_EMISSION | \
589                                   MAT_BIT_FRONT_AMBIENT | \
590                                   MAT_BIT_FRONT_DIFFUSE) << (side))
591 
592 
593 /**
594  * Either return a precalculated constant value or emit code to
595  * calculate these values dynamically in the case where material calls
596  * are present between begin/end pairs.
597  *
598  * Probably want to shift this to the program compilation phase - if
599  * we always emitted the calculation here, a smart compiler could
600  * detect that it was constant (given a certain set of inputs), and
601  * lift it out of the main loop.  That way the programs created here
602  * would be independent of the vertex_buffer details.
603  */
604 static nir_def *
get_scenecolor(struct tnl_program * p,GLuint side)605 get_scenecolor(struct tnl_program *p, GLuint side)
606 {
607    if (p->materials & SCENE_COLOR_BITS(side)) {
608       nir_def *lm_ambient =
609          load_state_vec4(p, STATE_LIGHTMODEL_AMBIENT, 0, 0, 0);
610       nir_def *material_emission =
611          get_material(p, side, STATE_EMISSION);
612       nir_def *material_ambient =
613          get_material(p, side, STATE_AMBIENT);
614       nir_def *material_diffuse =
615          get_material(p, side, STATE_DIFFUSE);
616 
617       // rgb: material_emission + material_ambient * lm_ambient
618       // alpha: material_diffuse.a
619       return nir_vector_insert_imm(p->b, nir_fmad(p->b,
620                                                   lm_ambient,
621                                                   material_ambient,
622                                                   material_emission),
623                                    nir_channel(p->b,
624                                                material_diffuse,
625                                                3),
626                                    3);
627    }
628    else
629       return load_state_vec4(p, STATE_LIGHTMODEL_SCENECOLOR, side, 0, 0);
630 }
631 
632 static nir_def *
get_lightprod(struct tnl_program * p,GLuint light,GLuint side,GLuint property,bool * is_state_light)633 get_lightprod(struct tnl_program *p, GLuint light,
634               GLuint side, GLuint property, bool *is_state_light)
635 {
636    GLuint attrib = material_attrib(side, property);
637    if (p->materials & (1<<attrib)) {
638       *is_state_light = true;
639       return load_state_vec4(p, STATE_LIGHT, light, property, 0);
640    } else {
641       *is_state_light = false;
642       return load_state_vec4(p, STATE_LIGHTPROD, light, attrib, 0);
643    }
644 }
645 
646 
647 static nir_def *
calculate_light_attenuation(struct tnl_program * p,GLuint i,nir_def * VPpli,nir_def * dist)648 calculate_light_attenuation(struct tnl_program *p,
649                             GLuint i,
650                             nir_def *VPpli,
651                             nir_def *dist)
652 {
653    nir_def *attenuation = NULL;
654    nir_def *att = NULL;
655 
656    /* Calculate spot attenuation:
657     */
658    if (!p->state->unit[i].light_spotcutoff_is_180) {
659        nir_def *spot_dir_norm =
660          load_state_vec4(p, STATE_LIGHT_SPOT_DIR_NORMALIZED, i, 0, 0);
661       attenuation =
662          load_state_vec4(p, STATE_LIGHT, i, STATE_ATTENUATION, 0);
663 
664       nir_def *spot = nir_fdot3(p->b, nir_fneg(p->b, VPpli),
665                                     spot_dir_norm);
666       nir_def *cmp = nir_flt(p->b, nir_channel(p->b, spot_dir_norm, 3),
667                                  spot);
668       spot = nir_fpow(p->b, spot, nir_channel(p->b, attenuation, 3));
669       att = nir_bcsel(p->b, cmp, spot, nir_imm_zero(p->b, 1, 32));
670    }
671 
672    /* Calculate distance attenuation(See formula (2.4) at glspec 2.1 page 62):
673     *
674     * Skip the calucation when _dist_ is undefined(light_eyepos3_is_zero)
675     */
676    if (p->state->unit[i].light_attenuated && dist) {
677       if (!attenuation) {
678          attenuation = load_state_vec4(p, STATE_LIGHT, i,
679                                        STATE_ATTENUATION, 0);
680       }
681 
682       /* dist is the reciprocal of ||VP|| used in the distance
683        * attenuation formula. So need to get the reciprocal of dist first
684        * before applying to the formula.
685        */
686       dist = nir_frcp(p->b, dist);
687 
688       /* 1, d, d*d */
689       nir_def *tmp = nir_vec3(p->b,
690          nir_imm_float(p->b, 1.0f),
691          dist,
692          nir_fmul(p->b, dist, dist)
693       );
694       tmp = nir_frcp(p->b, nir_fdot3(p->b, tmp, attenuation));
695 
696       if (!p->state->unit[i].light_spotcutoff_is_180)
697          return nir_fmul(p->b, tmp, att);
698       return tmp;
699    }
700 
701    return att;
702 }
703 
704 static nir_def *
emit_lit(nir_builder * b,nir_def * src)705 emit_lit(nir_builder *b,
706          nir_def *src)
707 {
708    nir_def *zero = nir_imm_zero(b, 1, 32);
709    nir_def *one = nir_imm_float(b, 1.0f);
710    nir_def *src_x = nir_channel(b, src, 0);
711    nir_def *src_y = nir_channel(b, src, 1);
712    nir_def *src_w = nir_channel(b, src, 3);
713 
714    nir_def *wclamp = nir_fmax(b, nir_fmin(b, src_w,
715                                               nir_imm_float(b, 128.0f)),
716                                   nir_imm_float(b, -128.0f));
717    nir_def *pow = nir_fpow(b, nir_fmax(b, src_y, zero), wclamp);
718 
719    return nir_vec4(b,
720                    one,
721                    nir_fmax(b, src_x, zero),
722                    nir_bcsel(b,
723                              nir_fge(b, zero, src_x),
724                              zero,
725                              pow),
726                    one);
727 }
728 
729 /**
730  * Compute:
731  *   lit.y = MAX(0, dots.x)
732  *   lit.z = SLT(0, dots.x)
733  */
734 static nir_def *
emit_degenerate_lit(nir_builder * b,nir_def * dots)735 emit_degenerate_lit(nir_builder *b,
736                     nir_def *dots)
737 {
738    nir_def *id = nir_imm_vec4(b, 0.0f, 0.0f, 0.0f, 1.0f);
739 
740    /* Note that lit.x & lit.w will not be examined.  Note also that
741     * dots.xyzw == dots.xxxx.
742     */
743 
744    nir_def *zero = nir_imm_zero(b, 1, 32);
745    nir_def *dots_x = nir_channel(b, dots, 0);
746    nir_def *tmp = nir_fmax(b, id, dots);
747    return nir_vector_insert_imm(b, tmp, nir_slt(b, zero, dots_x), 2);
748 }
749 
750 
751 /* Need to add some addtional parameters to allow lighting in object
752  * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
753  * space lighting.
754  */
build_lighting(struct tnl_program * p)755 static void build_lighting( struct tnl_program *p )
756 {
757    const GLboolean twoside = p->state->light_twoside;
758    const GLboolean separate = p->state->separate_specular;
759    GLuint nr_lights = 0;
760    nir_def *lit = NULL;
761    nir_def *dots = nir_imm_zero(p->b, 4, 32);
762    nir_def *normal = get_transformed_normal(p);
763    nir_def *_col0 = NULL, *_col1 = NULL;
764    nir_def *_bfc0 = NULL, *_bfc1 = NULL;
765    GLuint i;
766 
767    /*
768     * NOTE:
769     * dots.x = dot(normal, VPpli)
770     * dots.y = dot(normal, halfAngle)
771     * dots.z = back.shininess
772     * dots.w = front.shininess
773     */
774 
775    for (i = 0; i < MAX_LIGHTS; i++)
776       if (p->state->unit[i].light_enabled)
777          nr_lights++;
778 
779    set_material_flags(p);
780 
781    {
782       if (!p->state->material_shininess_is_zero) {
783          nir_def *shininess = get_material(p, 0, STATE_SHININESS);
784          nir_def *tmp = nir_channel(p->b, shininess, 0);
785          dots = nir_vector_insert_imm(p->b, dots, tmp, 3);
786       }
787 
788       _col0 = get_scenecolor(p, 0);
789       if (separate)
790          _col1 = nir_imm_vec4(p->b, 0.0f, 0.0f, 0.0f, 1.0f);
791    }
792 
793    if (twoside) {
794       if (!p->state->material_shininess_is_zero) {
795          /* Note that we negate the back-face specular exponent here.
796           * The negation will be un-done later in the back-face code below.
797           */
798          nir_def *shininess = get_material(p, 1, STATE_SHININESS);
799          nir_def *tmp = nir_channel(p->b, shininess, 0);
800          tmp = nir_fneg(p->b, tmp);
801          dots = nir_vector_insert_imm(p->b, dots, tmp, 2);
802       }
803 
804       _bfc0 = get_scenecolor(p, 1);
805       if (separate)
806          _bfc1 = nir_imm_vec4(p->b, 0.0f, 0.0f, 0.0f, 1.0f);
807    }
808 
809    /* If no lights, still need to emit the scenecolor.
810     */
811    store_output_vec4(p, VARYING_SLOT_COL0, _col0);
812 
813    if (separate)
814       store_output_vec4(p, VARYING_SLOT_COL1, _col1);
815 
816    if (twoside)
817       store_output_vec4(p, VARYING_SLOT_BFC0, _bfc0);
818 
819    if (twoside && separate)
820       store_output_vec4(p, VARYING_SLOT_BFC1, _bfc1);
821 
822    if (nr_lights == 0)
823       return;
824 
825    /* Declare light products first to place them sequentially next to each
826     * other for optimal constant uploads.
827     */
828    nir_def *lightprod_front[MAX_LIGHTS][3];
829    nir_def *lightprod_back[MAX_LIGHTS][3];
830    bool lightprod_front_is_state_light[MAX_LIGHTS][3];
831    bool lightprod_back_is_state_light[MAX_LIGHTS][3];
832 
833    for (i = 0; i < MAX_LIGHTS; i++) {
834       if (p->state->unit[i].light_enabled) {
835          lightprod_front[i][0] = get_lightprod(p, i, 0, STATE_AMBIENT,
836                                                &lightprod_front_is_state_light[i][0]);
837          if (twoside)
838             lightprod_back[i][0] = get_lightprod(p, i, 1, STATE_AMBIENT,
839                                                  &lightprod_back_is_state_light[i][0]);
840 
841          lightprod_front[i][1] = get_lightprod(p, i, 0, STATE_DIFFUSE,
842                                                &lightprod_front_is_state_light[i][1]);
843          if (twoside)
844             lightprod_back[i][1] = get_lightprod(p, i, 1, STATE_DIFFUSE,
845                                                  &lightprod_back_is_state_light[i][1]);
846 
847          lightprod_front[i][2] = get_lightprod(p, i, 0, STATE_SPECULAR,
848                                                &lightprod_front_is_state_light[i][2]);
849          if (twoside)
850             lightprod_back[i][2] = get_lightprod(p, i, 1, STATE_SPECULAR,
851                                                  &lightprod_back_is_state_light[i][2]);
852       }
853    }
854 
855    /* Add more variables now that we'll use later, so that they are nicely
856     * sorted in the parameter list.
857     */
858    for (i = 0; i < MAX_LIGHTS; i++) {
859       if (p->state->unit[i].light_enabled) {
860          if (p->state->unit[i].light_eyepos3_is_zero)
861             register_state_var(p, STATE_LIGHT_POSITION_NORMALIZED,
862                                i, 0, 0,
863                                glsl_vector_type(GLSL_TYPE_FLOAT, 3));
864          else
865             register_state_var(p, STATE_LIGHT_POSITION, i, 0, 0,
866                                glsl_vec4_type());
867       }
868    }
869    for (i = 0; i < MAX_LIGHTS; i++) {
870       if (p->state->unit[i].light_enabled &&
871           (!p->state->unit[i].light_spotcutoff_is_180 ||
872            (p->state->unit[i].light_attenuated &&
873             !p->state->unit[i].light_eyepos3_is_zero)))
874          register_state_var(p, STATE_LIGHT, i, STATE_ATTENUATION, 0,
875                             glsl_vec4_type());
876    }
877 
878    for (i = 0; i < MAX_LIGHTS; i++) {
879       if (p->state->unit[i].light_enabled) {
880          nir_def *half = NULL;
881          nir_def *att = NULL, *VPpli = NULL;
882          nir_def *dist = NULL;
883 
884          if (p->state->unit[i].light_eyepos3_is_zero) {
885             VPpli = load_state_var(p, STATE_LIGHT_POSITION_NORMALIZED,
886                                    i, 0, 0,
887                                    glsl_vector_type(GLSL_TYPE_FLOAT, 3));
888          } else {
889             nir_def *Ppli =
890                load_state_vec4(p, STATE_LIGHT_POSITION, i, 0, 0);
891 
892             nir_def *V = get_eye_position(p);
893             VPpli = nir_fsub(p->b, Ppli, V);
894 
895             /* Normalize VPpli.  The dist value also used in
896              * attenuation below.
897              */
898             dist = nir_frsq(p->b, nir_fdot3(p->b, VPpli, VPpli));
899             VPpli = nir_fmul(p->b, VPpli, dist);
900          }
901 
902          /* Calculate attenuation:
903           */
904          att = calculate_light_attenuation(p, i, VPpli, dist);
905 
906          /* Calculate viewer direction, or use infinite viewer:
907           */
908          if (!p->state->material_shininess_is_zero) {
909             if (p->state->light_local_viewer) {
910                nir_def *eye_hat = get_eye_position_normalized(p);
911                half = emit_normalize_vec3(p->b,
912                                           nir_fsub(p->b, VPpli, eye_hat));
913             } else if (p->state->unit[i].light_eyepos3_is_zero) {
914                half =
915                   load_state_var(p, STATE_LIGHT_HALF_VECTOR,
916                                  i, 0, 0,
917                                  glsl_vector_type(GLSL_TYPE_FLOAT, 3));
918             } else {
919                nir_def *tmp =
920                   nir_fadd(p->b,
921                            VPpli,
922                            nir_imm_vec3(p->b, 0.0f, 0.0f, 1.0f));
923                half = emit_normalize_vec3(p->b, tmp);
924             }
925          }
926 
927          /* Calculate dot products:
928           */
929          nir_def *dot = nir_fdot3(p->b, normal, VPpli);
930          if (p->state->material_shininess_is_zero) {
931             dots = nir_replicate(p->b, dot, 4);
932          } else {
933             dots = nir_vector_insert_imm(p->b, dots, dot, 0);
934             dot = nir_fdot3(p->b, normal, half);
935             dots = nir_vector_insert_imm(p->b, dots, dot, 1);
936          }
937 
938          /* Front face lighting:
939           */
940          {
941             /* Transform STATE_LIGHT into STATE_LIGHTPROD if needed. This isn't done in
942             * get_lightprod to avoid using too many temps.
943             */
944             for (int j = 0; j < 3; j++) {
945                if (lightprod_front_is_state_light[i][j]) {
946                   nir_def *material =
947                      get_material(p, 0, STATE_AMBIENT + j);
948                   lightprod_front[i][j] =
949                      nir_fmul(p->b, lightprod_front[i][j], material);
950                }
951             }
952 
953             nir_def *ambient = lightprod_front[i][0];
954             nir_def *diffuse = lightprod_front[i][1];
955             nir_def *specular = lightprod_front[i][2];
956 
957             if (att) {
958                /* light is attenuated by distance */
959                lit = emit_lit(p->b, dots);
960                lit = nir_fmul(p->b, lit, att);
961                _col0 = nir_fmad(p->b, nir_channel(p->b, lit, 0), ambient, _col0);
962             } else if (!p->state->material_shininess_is_zero) {
963                /* there's a non-zero specular term */
964                lit = emit_lit(p->b, dots);
965                _col0 = nir_fadd(p->b, ambient, _col0);
966             } else {
967                /* no attenutation, no specular */
968                lit = emit_degenerate_lit(p->b, dots);
969                _col0 = nir_fadd(p->b, ambient, _col0);
970             }
971 
972             _col0 = nir_fmad(p->b, nir_channel(p->b, lit, 1),
973                              diffuse, _col0);
974             if (separate)
975                _col1 = nir_fmad(p->b, nir_channel(p->b, lit, 2),
976                                 specular, _col1);
977             else
978                _col0 = nir_fmad(p->b, nir_channel(p->b, lit, 2),
979                                 specular, _col0);
980          }
981          /* Back face lighting:
982           */
983          nir_def *old_dots = dots;
984          if (twoside) {
985             /* Transform STATE_LIGHT into STATE_LIGHTPROD if needed. This isn't done in
986             * get_lightprod to avoid using too many temps.
987             */
988             for (int j = 0; j < 3; j++) {
989                if (lightprod_back_is_state_light[i][j]) {
990                   nir_def *material =
991                      get_material(p, 1, STATE_AMBIENT + j);
992                   lightprod_back[i][j] =
993                      nir_fmul(p->b, lightprod_back[i][j], material);
994                }
995             }
996 
997             nir_def *ambient = lightprod_back[i][0];
998             nir_def *diffuse = lightprod_back[i][1];
999             nir_def *specular = lightprod_back[i][2];
1000 
1001             /* For the back face we need to negate the X and Y component
1002              * dot products.  dots.Z has the negated back-face specular
1003              * exponent.  We swizzle that into the W position.  This
1004              * negation makes the back-face specular term positive again.
1005              */
1006             unsigned swiz_xywz[] = {0, 1, 3, 2};
1007             nir_def *dots =
1008                nir_fneg(p->b, nir_swizzle(p->b, old_dots, swiz_xywz, 4));
1009 
1010             if (att) {
1011                /* light is attenuated by distance */
1012                lit = emit_lit(p->b, dots);
1013                lit = nir_fmul(p->b, lit, att);
1014                _bfc0 = nir_fmad(p->b, nir_channel(p->b, lit, 0), ambient, _bfc0);
1015             } else if (!p->state->material_shininess_is_zero) {
1016                /* there's a non-zero specular term */
1017                lit = emit_lit(p->b, dots);
1018                _bfc0 = nir_fadd(p->b, ambient, _bfc0);
1019             } else {
1020                /* no attenutation, no specular */
1021                lit = emit_degenerate_lit(p->b, dots);
1022                _bfc0 = nir_fadd(p->b, ambient, _bfc0);
1023             }
1024 
1025             _bfc0 = nir_fmad(p->b, nir_channel(p->b, lit, 1),
1026                              diffuse, _bfc0);
1027             if (separate)
1028                _bfc1 = nir_fmad(p->b, nir_channel(p->b, lit, 2),
1029                                 specular, _bfc1);
1030             else
1031                _bfc0 = nir_fmad(p->b, nir_channel(p->b, lit, 2),
1032                                 specular, _bfc0);
1033          }
1034       }
1035    }
1036 
1037    store_output_vec4_masked(p, VARYING_SLOT_COL0, _col0, 0x7);
1038    if (separate)
1039       store_output_vec4_masked(p, VARYING_SLOT_COL1, _col1, 0x7);
1040 
1041    if (twoside) {
1042       store_output_vec4_masked(p, VARYING_SLOT_BFC0, _bfc0, 0x7);
1043       if (separate)
1044          store_output_vec4_masked(p, VARYING_SLOT_BFC1, _bfc1, 0x7);
1045    }
1046 }
1047 
1048 
build_fog(struct tnl_program * p)1049 static void build_fog( struct tnl_program *p )
1050 {
1051    nir_def *fog;
1052    switch (p->state->fog_distance_mode) {
1053    case FDM_EYE_RADIAL:
1054       /* Z = sqrt(Xe*Xe + Ye*Ye + Ze*Ze) */
1055       fog = nir_fast_length(p->b,
1056                             nir_trim_vector(p->b, get_eye_position(p), 3));
1057       break;
1058    case FDM_EYE_PLANE: /* Z = Ze */
1059       fog = get_eye_position_z(p);
1060       break;
1061    case FDM_EYE_PLANE_ABS: /* Z = abs(Ze) */
1062       fog = nir_fabs(p->b, get_eye_position_z(p));
1063       break;
1064    case FDM_FROM_ARRAY:
1065       fog = load_input(p, VERT_ATTRIB_FOG, glsl_float_type());
1066       break;
1067    default:
1068       unreachable("Bad fog mode in build_fog()");
1069    }
1070 
1071    store_output_float(p, VARYING_SLOT_FOGC, fog);
1072 }
1073 
1074 
1075 static nir_def *
build_reflect_texgen(struct tnl_program * p)1076 build_reflect_texgen(struct tnl_program *p)
1077 {
1078    nir_def *normal = get_transformed_normal(p);
1079    nir_def *eye_hat = get_eye_position_normalized(p);
1080    /* n.u */
1081    nir_def *tmp = nir_fdot3(p->b, normal, eye_hat);
1082    /* 2n.u */
1083    tmp = nir_fadd(p->b, tmp, tmp);
1084    /* (-2n.u)n + u */
1085    return nir_fmad(p->b, nir_fneg(p->b, tmp), normal, eye_hat);
1086 }
1087 
1088 
1089 static nir_def *
build_sphere_texgen(struct tnl_program * p)1090 build_sphere_texgen(struct tnl_program *p)
1091 {
1092    nir_def *normal = get_transformed_normal(p);
1093    nir_def *eye_hat = get_eye_position_normalized(p);
1094 
1095    /* Could share the above calculations, but it would be
1096     * a fairly odd state for someone to set (both sphere and
1097     * reflection active for different texture coordinate
1098     * components.  Of course - if two texture units enable
1099     * reflect and/or sphere, things start to tilt in favour
1100     * of seperating this out:
1101     */
1102 
1103    /* n.u */
1104    nir_def *tmp = nir_fdot3(p->b, normal, eye_hat);
1105    /* 2n.u */
1106    tmp = nir_fadd(p->b, tmp, tmp);
1107    /* (-2n.u)n + u */
1108    nir_def *r = nir_fmad(p->b, nir_fneg(p->b, tmp), normal, eye_hat);
1109    /* r + 0,0,1 */
1110    tmp = nir_fadd(p->b, r, nir_imm_vec4(p->b, 0.0f, 0.0f, 1.0f, 0.0f));
1111    /* rx^2 + ry^2 + (rz+1)^2 */
1112    tmp = nir_fdot3(p->b, tmp, tmp);
1113    /* 2/m */
1114    tmp = nir_frsq(p->b, tmp);
1115    /* 1/m */
1116    nir_def *inv_m = nir_fmul_imm(p->b, tmp, 0.5f);
1117    /* r/m + 1/2 */
1118    return nir_fmad(p->b, r, inv_m, nir_imm_float(p->b, 0.5f));
1119 }
1120 
build_texture_transform(struct tnl_program * p)1121 static void build_texture_transform( struct tnl_program *p )
1122 {
1123    GLuint i, j;
1124 
1125    for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
1126 
1127       if (!(p->state->fragprog_inputs_read & VARYING_BIT_TEX(i)))
1128          continue;
1129 
1130       if (p->state->unit[i].coord_replace)
1131          continue;
1132 
1133       nir_def *texcoord;
1134       if (p->state->unit[i].texgen_enabled) {
1135          GLuint copy_mask = 0;
1136          GLuint sphere_mask = 0;
1137          GLuint reflect_mask = 0;
1138          GLuint normal_mask = 0;
1139          GLuint modes[4];
1140          nir_def *comps[4];
1141 
1142          modes[0] = p->state->unit[i].texgen_mode0;
1143          modes[1] = p->state->unit[i].texgen_mode1;
1144          modes[2] = p->state->unit[i].texgen_mode2;
1145          modes[3] = p->state->unit[i].texgen_mode3;
1146 
1147          for (j = 0; j < 4; j++) {
1148             switch (modes[j]) {
1149             case TXG_OBJ_LINEAR: {
1150                nir_def *obj = load_input_vec4(p, VERT_ATTRIB_POS);
1151                nir_def *plane =
1152                   load_state_vec4(p, STATE_TEXGEN, i,
1153                                   STATE_TEXGEN_OBJECT_S + j, 0);
1154                comps[j] = nir_fdot4(p->b, obj, plane);
1155                break;
1156             }
1157             case TXG_EYE_LINEAR: {
1158                nir_def *eye = get_eye_position(p);
1159                nir_def *plane =
1160                   load_state_vec4(p, STATE_TEXGEN, i,
1161                                   STATE_TEXGEN_EYE_S + j, 0);
1162                comps[j] = nir_fdot4(p->b, eye, plane);
1163                break;
1164             }
1165             case TXG_SPHERE_MAP:
1166                sphere_mask |= 1u << j;
1167                break;
1168             case TXG_REFLECTION_MAP:
1169                reflect_mask |= 1u << j;
1170                break;
1171             case TXG_NORMAL_MAP:
1172                normal_mask |= 1u << j;
1173                break;
1174             case TXG_NONE:
1175                copy_mask |= 1u << j;
1176             }
1177          }
1178 
1179          if (sphere_mask) {
1180             nir_def *sphere = build_sphere_texgen(p);
1181             for (j = 0; j < 4; j++)
1182                if (sphere_mask & (1 << j))
1183                   comps[j] = nir_channel(p->b, sphere, j);
1184          }
1185 
1186          if (reflect_mask) {
1187             nir_def *reflect = build_reflect_texgen(p);
1188             for (j = 0; j < 4; j++)
1189                if (reflect_mask & (1 << j))
1190                   comps[j] = nir_channel(p->b, reflect, j);
1191          }
1192 
1193          if (normal_mask) {
1194             nir_def *normal = get_transformed_normal(p);
1195             for (j = 0; j < 4; j++)
1196                if (normal_mask & (1 << j))
1197                   comps[j] = nir_channel(p->b, normal, j);
1198          }
1199 
1200          if (copy_mask) {
1201             nir_def *in = load_input_vec4(p, VERT_ATTRIB_TEX0 + i);
1202             for (j = 0; j < 4; j++)
1203                if (copy_mask & (1 << j))
1204                   comps[j] = nir_channel(p->b, in, j);
1205          }
1206 
1207          texcoord = nir_vec(p->b, comps, 4);
1208       } else
1209          texcoord = load_input_vec4(p, VERT_ATTRIB_TEX0 + i);
1210 
1211       if (p->state->unit[i].texmat_enabled) {
1212          nir_def *texmat[4];
1213          if (p->mvp_with_dp4) {
1214             load_state_mat4(p, texmat, STATE_TEXTURE_MATRIX, i);
1215             texcoord =
1216                emit_matrix_transform_vec4(p->b, texmat, texcoord);
1217          } else {
1218             load_state_mat4(p, texmat,
1219                             STATE_TEXTURE_MATRIX_TRANSPOSE, i);
1220             texcoord =
1221                emit_transpose_matrix_transform_vec4(p->b, texmat,
1222                                                       texcoord);
1223          }
1224       }
1225 
1226       store_output_vec4(p, VARYING_SLOT_TEX0 + i, texcoord);
1227    }
1228 }
1229 
1230 
1231 /**
1232  * Point size attenuation computation.
1233  */
build_atten_pointsize(struct tnl_program * p)1234 static void build_atten_pointsize( struct tnl_program *p )
1235 {
1236    nir_def *eye = get_eye_position_z(p);
1237    nir_def *in_size =
1238       load_state_vec4(p, STATE_POINT_SIZE_CLAMPED, 0, 0, 0);
1239    nir_def *att =
1240       load_state_vec4(p, STATE_POINT_ATTENUATION, 0, 0, 0);
1241 
1242    /* dist = |eyez| */
1243    nir_def *dist = nir_fabs(p->b, eye);
1244 
1245    /* p1 + dist * (p2 + dist * p3); */
1246    nir_def *factor = nir_fmad(p->b, dist, nir_channel(p->b, att, 2),
1247                                               nir_channel(p->b, att, 1));
1248    factor = nir_fmad(p->b, dist, factor, nir_channel(p->b, att, 0));
1249 
1250    /* 1 / sqrt(factor) */
1251    factor = nir_frsq(p->b, factor);
1252 
1253    /* pointSize / sqrt(factor) */
1254    nir_def *size = nir_fmul(p->b, factor,
1255                                 nir_channel(p->b, in_size, 0));
1256 
1257 #if 1
1258    /* this is a good place to clamp the point size since there's likely
1259     * no hardware registers to clamp point size at rasterization time.
1260     */
1261    size = nir_fclamp(p->b, size, nir_channel(p->b, in_size, 1),
1262                                  nir_channel(p->b, in_size, 2));
1263 #endif
1264 
1265    store_output_float(p, VARYING_SLOT_PSIZ, size);
1266 }
1267 
1268 
1269 /**
1270  * Pass-though per-vertex point size, from user's point size array.
1271  */
build_array_pointsize(struct tnl_program * p)1272 static void build_array_pointsize( struct tnl_program *p )
1273 {
1274    nir_def *val = load_input(p, VERT_ATTRIB_POINT_SIZE,
1275                                  glsl_float_type());
1276    store_output_float(p, VARYING_SLOT_PSIZ, val);
1277 }
1278 
1279 
build_tnl_program(struct tnl_program * p)1280 static void build_tnl_program( struct tnl_program *p )
1281 {
1282    /* Emit the program (except for the MVP transform, which is a separate pass) */
1283 
1284    /* Lighting calculations:
1285     */
1286    if (p->state->fragprog_inputs_read &
1287        (VARYING_BIT_COL0 | VARYING_BIT_COL1)) {
1288       if (p->state->light_global_enabled)
1289          build_lighting(p);
1290       else {
1291          if (p->state->fragprog_inputs_read & VARYING_BIT_COL0)
1292             emit_passthrough(p, VERT_ATTRIB_COLOR0, VARYING_SLOT_COL0);
1293 
1294          if (p->state->fragprog_inputs_read & VARYING_BIT_COL1)
1295             emit_passthrough(p, VERT_ATTRIB_COLOR1, VARYING_SLOT_COL1);
1296       }
1297    }
1298 
1299    if (p->state->fragprog_inputs_read & VARYING_BIT_FOGC)
1300       build_fog(p);
1301 
1302    if (p->state->fragprog_inputs_read & VARYING_BITS_TEX_ANY)
1303       build_texture_transform(p);
1304 
1305    if (p->state->point_attenuated)
1306       build_atten_pointsize(p);
1307    else if (p->state->varying_vp_inputs & VERT_BIT_POINT_SIZE)
1308       build_array_pointsize(p);
1309 
1310    if (p->state->varying_vp_inputs & VERT_BIT_SELECT_RESULT_OFFSET)
1311       emit_passthrough(p, VERT_ATTRIB_SELECT_RESULT_OFFSET,
1312                        VARYING_SLOT_VAR0);
1313 }
1314 
1315 
1316 static nir_shader *
create_new_program(const struct state_key * key,struct gl_program * program,GLboolean mvp_with_dp4,const nir_shader_compiler_options * options)1317 create_new_program( const struct state_key *key,
1318                     struct gl_program *program,
1319                     GLboolean mvp_with_dp4,
1320                     const nir_shader_compiler_options *options)
1321 {
1322    struct tnl_program p;
1323 
1324    memset(&p, 0, sizeof(p));
1325    p.state = key;
1326    p.mvp_with_dp4 = mvp_with_dp4;
1327 
1328    program->Parameters = _mesa_new_parameter_list();
1329    p.state_params = _mesa_new_parameter_list();
1330 
1331    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX,
1332                                                   options,
1333                                                   "ff-vs");
1334 
1335    nir_shader *s = b.shader;
1336 
1337    s->info.separate_shader = true;
1338 
1339    p.b = &b;
1340 
1341    build_tnl_program( &p );
1342 
1343    nir_validate_shader(b.shader, "after generating ff-vertex shader");
1344 
1345    /* Emit the MVP position transformation */
1346    NIR_PASS(_, b.shader, st_nir_lower_position_invariant, mvp_with_dp4, p.state_params);
1347 
1348    _mesa_add_separate_state_parameters(program, p.state_params);
1349    _mesa_free_parameter_list(p.state_params);
1350 
1351    return s;
1352 }
1353 
1354 
1355 /**
1356  * Return a vertex program which implements the current fixed-function
1357  * transform/lighting/texgen operations.
1358  */
1359 struct gl_program *
_mesa_get_fixed_func_vertex_program(struct gl_context * ctx)1360 _mesa_get_fixed_func_vertex_program(struct gl_context *ctx)
1361 {
1362    struct gl_program *prog;
1363    struct state_key key;
1364 
1365    /* We only update ctx->VertexProgram._VaryingInputs when in VP_MODE_FF _VPMode */
1366    assert(VP_MODE_FF == ctx->VertexProgram._VPMode);
1367 
1368    /* Grab all the relevant state and put it in a single structure:
1369     */
1370    make_state_key(ctx, &key);
1371 
1372    /* Look for an already-prepared program for this state:
1373     */
1374    prog = _mesa_search_program_cache(ctx->VertexProgram.Cache, &key,
1375                                      sizeof(key));
1376 
1377    if (!prog) {
1378       /* OK, we'll have to build a new one */
1379       if (0)
1380          printf("Build new TNL program\n");
1381 
1382       prog = ctx->Driver.NewProgram(ctx, MESA_SHADER_VERTEX, 0, false);
1383       if (!prog)
1384          return NULL;
1385 
1386       const struct nir_shader_compiler_options *options =
1387          st_get_nir_compiler_options(ctx->st, MESA_SHADER_VERTEX);
1388 
1389       nir_shader *s =
1390          create_new_program( &key, prog,
1391                              ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS,
1392                              options);
1393 
1394       prog->state.type = PIPE_SHADER_IR_NIR;
1395       prog->nir = s;
1396 
1397       st_program_string_notify(ctx, GL_VERTEX_PROGRAM_ARB, prog);
1398 
1399       _mesa_program_cache_insert(ctx, ctx->VertexProgram.Cache, &key,
1400                                  sizeof(key), prog);
1401    }
1402 
1403    return prog;
1404 }
1405