1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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 TUNGSTEN GRAPHICS 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.
26 **************************************************************************/
29 * State validation for vertex/fragment shaders.
30 * Note that we have to delay most vertex/fragment shader translation
31 * until rendering time since the linkage between the vertex outputs and
32 * fragment inputs can vary depending on the pairing of shaders.
40 #include "main/imports.h"
41 #include "main/mtypes.h"
42 #include "main/macros.h"
43 #include "shader/program.h"
45 #include "pipe/p_context.h"
46 #include "pipe/p_shader_tokens.h"
48 #include "util/u_simple_shaders.h"
50 #include "cso_cache/cso_context.h"
52 #include "st_context.h"
54 #include "st_program.h"
55 #include "st_atom_shader.h"
56 #include "st_mesa_to_tgsi.h"
60 * This represents a vertex program, especially translated to match
61 * the inputs of a particular fragment shader.
63 struct translated_vertex_program
65 struct st_vertex_program
*master
;
67 /** The fragment shader "signature" this vertex shader is meant for: */
68 GLbitfield frag_inputs
;
70 /** Compared against master vertex program's serialNo: */
73 /** Maps VERT_RESULT_x to slot */
74 GLuint output_to_slot
[VERT_RESULT_MAX
];
75 ubyte output_to_semantic_name
[VERT_RESULT_MAX
];
76 ubyte output_to_semantic_index
[VERT_RESULT_MAX
];
78 /** Pointer to the translated vertex program */
79 struct st_vertex_program
*vp
;
81 struct translated_vertex_program
*next
; /**< next in linked list */
87 * Given a vertex program output attribute, return the corresponding
88 * fragment program input attribute.
89 * \return -1 for vertex outputs that have no corresponding fragment input
92 vp_out_to_fp_in(GLuint vertResult
)
94 if (vertResult
>= VERT_RESULT_TEX0
&&
95 vertResult
< VERT_RESULT_TEX0
+ MAX_TEXTURE_COORD_UNITS
)
96 return FRAG_ATTRIB_TEX0
+ (vertResult
- VERT_RESULT_TEX0
);
98 if (vertResult
>= VERT_RESULT_VAR0
&&
99 vertResult
< VERT_RESULT_VAR0
+ MAX_VARYING
)
100 return FRAG_ATTRIB_VAR0
+ (vertResult
- VERT_RESULT_VAR0
);
102 switch (vertResult
) {
103 case VERT_RESULT_HPOS
:
104 return FRAG_ATTRIB_WPOS
;
105 case VERT_RESULT_COL0
:
106 return FRAG_ATTRIB_COL0
;
107 case VERT_RESULT_COL1
:
108 return FRAG_ATTRIB_COL1
;
109 case VERT_RESULT_FOGC
:
110 return FRAG_ATTRIB_FOGC
;
112 /* Back-face colors, edge flags, etc */
119 * Find a translated vertex program that corresponds to stvp and
120 * has outputs matched to stfp's inputs.
121 * This performs vertex and fragment translation (to TGSI) when needed.
123 static struct translated_vertex_program
*
124 find_translated_vp(struct st_context
*st
,
125 struct st_vertex_program
*stvp
,
126 struct st_fragment_program
*stfp
)
128 static const GLuint UNUSED
= ~0;
129 struct translated_vertex_program
*xvp
;
130 const GLbitfield fragInputsRead
= stfp
->Base
.Base
.InputsRead
;
133 * Translate fragment program if needed.
135 if (!stfp
->state
.tokens
) {
136 GLuint inAttr
, numIn
= 0;
138 for (inAttr
= 0; inAttr
< FRAG_ATTRIB_MAX
; inAttr
++) {
139 if (fragInputsRead
& (1 << inAttr
)) {
140 stfp
->input_to_slot
[inAttr
] = numIn
;
142 if ((fragInputsRead
& FRAG_BIT_FOGC
)) {
143 /* leave placeholders for the
144 * extra registers we extract from fog */
145 if (stfp
->Base
.UsesFrontFacing
) {
146 if (!stfp
->Base
.UsesFogFragCoord
)
147 --stfp
->input_to_slot
[inAttr
];
151 if (stfp
->Base
.UsesPointCoord
) {
152 if (!stfp
->Base
.UsesFrontFacing
&&
153 !stfp
->Base
.UsesFogFragCoord
)
154 stfp
->input_to_slot
[inAttr
] -= 2;
161 stfp
->input_to_slot
[inAttr
] = UNUSED
;
165 stfp
->num_input_slots
= numIn
;
167 assert(stfp
->Base
.Base
.NumInstructions
> 1);
169 st_translate_fragment_program(st
, stfp
, stfp
->input_to_slot
);
173 /* See if we've got a translated vertex program whose outputs match
174 * the fragment program's inputs.
175 * XXX This could be a hash lookup, using InputsRead as the key.
177 for (xvp
= stfp
->vertex_programs
; xvp
; xvp
= xvp
->next
) {
178 if (xvp
->master
== stvp
&& xvp
->frag_inputs
== fragInputsRead
) {
183 /* No? Allocate translated vp object now */
185 xvp
= ST_CALLOC_STRUCT(translated_vertex_program
);
186 xvp
->frag_inputs
= fragInputsRead
;
189 xvp
->next
= stfp
->vertex_programs
;
190 stfp
->vertex_programs
= xvp
;
193 /* See if we need to translate vertex program to TGSI form */
194 if (xvp
->serialNo
!= stvp
->serialNo
) {
196 const GLbitfield outputsWritten
= stvp
->Base
.Base
.OutputsWritten
;
197 GLuint numVpOuts
= 0;
198 GLboolean emitPntSize
= GL_FALSE
, emitBFC0
= GL_FALSE
, emitBFC1
= GL_FALSE
;
199 GLbitfield usedGenerics
= 0x0;
200 GLbitfield usedOutputSlots
= 0x0;
202 /* Compute mapping of vertex program outputs to slots, which depends
203 * on the fragment program's input->slot mapping.
205 for (outAttr
= 0; outAttr
< VERT_RESULT_MAX
; outAttr
++) {
207 xvp
->output_to_slot
[outAttr
] = UNUSED
;
208 xvp
->output_to_semantic_name
[outAttr
] = TGSI_SEMANTIC_COUNT
;
209 xvp
->output_to_semantic_index
[outAttr
] = 99;
211 if (outAttr
== VERT_RESULT_HPOS
) {
212 /* always put xformed position into slot zero */
214 xvp
->output_to_slot
[VERT_RESULT_HPOS
] = slot
;
215 xvp
->output_to_semantic_name
[outAttr
] = TGSI_SEMANTIC_POSITION
;
216 xvp
->output_to_semantic_index
[outAttr
] = 0;
218 usedOutputSlots
|= (1 << slot
);
220 else if (outputsWritten
& (1 << outAttr
)) {
221 /* see if the frag prog wants this vert output */
222 GLint fpInAttrib
= vp_out_to_fp_in(outAttr
);
223 if (fpInAttrib
>= 0) {
224 GLuint fpInSlot
= stfp
->input_to_slot
[fpInAttrib
];
225 if (fpInSlot
!= ~0) {
226 /* match this vp output to the fp input */
227 GLuint vpOutSlot
= stfp
->input_map
[fpInSlot
];
228 xvp
->output_to_slot
[outAttr
] = vpOutSlot
;
229 xvp
->output_to_semantic_name
[outAttr
] = stfp
->input_semantic_name
[fpInSlot
];
230 xvp
->output_to_semantic_index
[outAttr
] = stfp
->input_semantic_index
[fpInSlot
];
232 usedOutputSlots
|= (1 << vpOutSlot
);
236 printf("VP output %d not used by FP\n", outAttr
);
240 else if (outAttr
== VERT_RESULT_PSIZ
)
241 emitPntSize
= GL_TRUE
;
242 else if (outAttr
== VERT_RESULT_BFC0
)
244 else if (outAttr
== VERT_RESULT_BFC1
)
248 printf("assign vp output_to_slot[%d] = %d\n", outAttr
,
249 xvp
->output_to_slot
[outAttr
]);
253 /* must do these last */
255 GLuint slot
= numVpOuts
++;
256 xvp
->output_to_slot
[VERT_RESULT_PSIZ
] = slot
;
257 xvp
->output_to_semantic_name
[VERT_RESULT_PSIZ
] = TGSI_SEMANTIC_PSIZE
;
258 xvp
->output_to_semantic_index
[VERT_RESULT_PSIZ
] = 0;
259 usedOutputSlots
|= (1 << slot
);
262 GLuint slot
= numVpOuts
++;
263 xvp
->output_to_slot
[VERT_RESULT_BFC0
] = slot
;
264 xvp
->output_to_semantic_name
[VERT_RESULT_BFC0
] = TGSI_SEMANTIC_COLOR
;
265 xvp
->output_to_semantic_index
[VERT_RESULT_BFC0
] = 0;
266 usedOutputSlots
|= (1 << slot
);
269 GLuint slot
= numVpOuts
++;
270 xvp
->output_to_slot
[VERT_RESULT_BFC1
] = slot
;
271 xvp
->output_to_semantic_name
[VERT_RESULT_BFC1
] = TGSI_SEMANTIC_COLOR
;
272 xvp
->output_to_semantic_index
[VERT_RESULT_BFC1
] = 1;
273 usedOutputSlots
|= (1 << slot
);
276 /* build usedGenerics mask */
278 for (outAttr
= 0; outAttr
< VERT_RESULT_MAX
; outAttr
++) {
279 if (xvp
->output_to_semantic_name
[outAttr
] == TGSI_SEMANTIC_GENERIC
) {
280 usedGenerics
|= (1 << xvp
->output_to_semantic_index
[outAttr
]);
284 /* For each vertex program output that doesn't match up to a fragment
285 * program input, map the vertex program output to a free slot and
286 * free generic attribute.
288 for (outAttr
= 0; outAttr
< VERT_RESULT_MAX
; outAttr
++) {
289 if (outputsWritten
& (1 << outAttr
)) {
290 if (xvp
->output_to_slot
[outAttr
] == UNUSED
) {
291 GLint freeGeneric
= _mesa_ffs(~usedGenerics
) - 1;
292 GLint freeSlot
= _mesa_ffs(~usedOutputSlots
) - 1;
293 usedGenerics
|= (1 << freeGeneric
);
294 usedOutputSlots
|= (1 << freeSlot
);
295 xvp
->output_to_slot
[outAttr
] = freeSlot
;
296 xvp
->output_to_semantic_name
[outAttr
] = TGSI_SEMANTIC_GENERIC
;
297 xvp
->output_to_semantic_index
[outAttr
] = freeGeneric
;
302 printf("vp output_to_slot[%d] = %d\n", outAttr
,
303 xvp
->output_to_slot
[outAttr
]);
307 assert(stvp
->Base
.Base
.NumInstructions
> 1);
309 st_translate_vertex_program(st
, stvp
, xvp
->output_to_slot
,
310 xvp
->output_to_semantic_name
,
311 xvp
->output_to_semantic_index
);
315 /* translated VP is up to date now */
316 xvp
->serialNo
= stvp
->serialNo
;
324 st_free_translated_vertex_programs(struct st_context
*st
,
325 struct translated_vertex_program
*xvp
)
327 struct translated_vertex_program
*next
;
338 get_passthrough_fs(struct st_context
*st
)
340 if (!st
->passthrough_fs
) {
342 util_make_fragment_passthrough_shader(st
->pipe
);
345 return st
->passthrough_fs
;
350 update_linkage( struct st_context
*st
)
352 struct st_vertex_program
*stvp
;
353 struct st_fragment_program
*stfp
;
354 struct translated_vertex_program
*xvp
;
356 /* find active shader and params -- Should be covered by
357 * ST_NEW_VERTEX_PROGRAM
359 assert(st
->ctx
->VertexProgram
._Current
);
360 stvp
= st_vertex_program(st
->ctx
->VertexProgram
._Current
);
361 assert(stvp
->Base
.Base
.Target
== GL_VERTEX_PROGRAM_ARB
);
363 assert(st
->ctx
->FragmentProgram
._Current
);
364 stfp
= st_fragment_program(st
->ctx
->FragmentProgram
._Current
);
365 assert(stfp
->Base
.Base
.Target
== GL_FRAGMENT_PROGRAM_ARB
);
367 xvp
= find_translated_vp(st
, stvp
, stfp
);
369 st_reference_vertprog(st
, &st
->vp
, stvp
);
370 st_reference_fragprog(st
, &st
->fp
, stfp
);
372 cso_set_vertex_shader_handle(st
->cso_context
, stvp
->driver_shader
);
374 if (st
->missing_textures
) {
375 /* use a pass-through frag shader that uses no textures */
376 void *fs
= get_passthrough_fs(st
);
377 cso_set_fragment_shader_handle(st
->cso_context
, fs
);
380 cso_set_fragment_shader_handle(st
->cso_context
, stfp
->driver_shader
);
383 st
->vertex_result_to_slot
= xvp
->output_to_slot
;
387 const struct st_tracked_state st_update_shader
= {
388 "st_update_shader", /* name */
391 ST_NEW_VERTEX_PROGRAM
| ST_NEW_FRAGMENT_PROGRAM
/* st */
393 update_linkage
/* update */