gallium/draw: apply DRAW_PIPE_FLAG_MASK to all vertex elements
[mesa.git] / src / mesa / state_tracker / st_atom_shader.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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 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.
25 *
26 **************************************************************************/
27
28 /**
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.
33 *
34 * Authors:
35 * Brian Paul
36 */
37
38
39
40 #include "main/imports.h"
41 #include "main/mtypes.h"
42 #include "main/macros.h"
43 #include "shader/program.h"
44
45 #include "pipe/p_context.h"
46 #include "pipe/p_shader_tokens.h"
47
48 #include "util/u_simple_shaders.h"
49
50 #include "cso_cache/cso_context.h"
51
52 #include "st_context.h"
53 #include "st_atom.h"
54 #include "st_program.h"
55 #include "st_atom_shader.h"
56
57
58 /**
59 * This represents a vertex program, especially translated to match
60 * the inputs of a particular fragment shader.
61 */
62 struct translated_vertex_program
63 {
64 struct st_vertex_program *master;
65
66 /** The fragment shader "signature" this vertex shader is meant for: */
67 GLbitfield frag_inputs;
68
69 /** Compared against master vertex program's serialNo: */
70 GLuint serialNo;
71
72 /** Maps VERT_RESULT_x to slot */
73 GLuint output_to_slot[VERT_RESULT_MAX];
74 ubyte output_to_semantic_name[VERT_RESULT_MAX];
75 ubyte output_to_semantic_index[VERT_RESULT_MAX];
76
77 /** Pointer to the translated vertex program */
78 struct st_vertex_program *vp;
79
80 struct translated_vertex_program *next; /**< next in linked list */
81 };
82
83
84
85 /**
86 * Given a vertex program output attribute, return the corresponding
87 * fragment program input attribute.
88 * \return -1 for vertex outputs that have no corresponding fragment input
89 */
90 static GLint
91 vp_out_to_fp_in(GLuint vertResult)
92 {
93 if (vertResult >= VERT_RESULT_TEX0 &&
94 vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
95 return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
96
97 if (vertResult >= VERT_RESULT_VAR0 &&
98 vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
99 return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
100
101 switch (vertResult) {
102 case VERT_RESULT_HPOS:
103 return FRAG_ATTRIB_WPOS;
104 case VERT_RESULT_COL0:
105 return FRAG_ATTRIB_COL0;
106 case VERT_RESULT_COL1:
107 return FRAG_ATTRIB_COL1;
108 case VERT_RESULT_FOGC:
109 return FRAG_ATTRIB_FOGC;
110 default:
111 /* Back-face colors, edge flags, etc */
112 return -1;
113 }
114 }
115
116
117 /**
118 * Find a translated vertex program that corresponds to stvp and
119 * has outputs matched to stfp's inputs.
120 * This performs vertex and fragment translation (to TGSI) when needed.
121 */
122 static struct translated_vertex_program *
123 find_translated_vp(struct st_context *st,
124 struct st_vertex_program *stvp,
125 struct st_fragment_program *stfp)
126 {
127 static const GLuint UNUSED = ~0;
128 struct translated_vertex_program *xvp;
129 const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
130
131 /*
132 * Translate fragment program if needed.
133 */
134 if (!stfp->state.tokens) {
135 GLuint inAttr, numIn = 0;
136
137 for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
138 if (fragInputsRead & (1 << inAttr)) {
139 stfp->input_to_slot[inAttr] = numIn;
140 numIn++;
141 }
142 else {
143 stfp->input_to_slot[inAttr] = UNUSED;
144 }
145 }
146
147 stfp->num_input_slots = numIn;
148
149 assert(stfp->Base.Base.NumInstructions > 0);
150
151 st_translate_fragment_program(st, stfp, stfp->input_to_slot);
152 }
153
154
155 /* See if we've got a translated vertex program whose outputs match
156 * the fragment program's inputs.
157 * XXX This could be a hash lookup, using InputsRead as the key.
158 */
159 for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
160 if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
161 break;
162 }
163 }
164
165 /* No? Allocate translated vp object now */
166 if (!xvp) {
167 xvp = ST_CALLOC_STRUCT(translated_vertex_program);
168 xvp->frag_inputs = fragInputsRead;
169 xvp->master = stvp;
170
171 xvp->next = stfp->vertex_programs;
172 stfp->vertex_programs = xvp;
173 }
174
175 /* See if we need to translate vertex program to TGSI form */
176 if (xvp->serialNo != stvp->serialNo) {
177 GLuint outAttr;
178 const GLbitfield64 outputsWritten = stvp->Base.Base.OutputsWritten;
179 GLuint numVpOuts = 0;
180 GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
181 GLbitfield usedGenerics = 0x0;
182 GLbitfield usedOutputSlots = 0x0;
183
184 /* Compute mapping of vertex program outputs to slots, which depends
185 * on the fragment program's input->slot mapping.
186 */
187 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
188 /* set defaults: */
189 xvp->output_to_slot[outAttr] = UNUSED;
190 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
191 xvp->output_to_semantic_index[outAttr] = 99;
192
193 if (outAttr == VERT_RESULT_HPOS) {
194 /* always put xformed position into slot zero */
195 GLuint slot = 0;
196 xvp->output_to_slot[VERT_RESULT_HPOS] = slot;
197 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
198 xvp->output_to_semantic_index[outAttr] = 0;
199 numVpOuts++;
200 usedOutputSlots |= (1 << slot);
201 }
202 else if (outputsWritten & (1 << outAttr)) {
203 /* see if the frag prog wants this vert output */
204 GLint fpInAttrib = vp_out_to_fp_in(outAttr);
205 if (fpInAttrib >= 0) {
206 GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
207 if (fpInSlot != ~0) {
208 /* match this vp output to the fp input */
209 GLuint vpOutSlot = stfp->input_map[fpInSlot];
210 xvp->output_to_slot[outAttr] = vpOutSlot;
211 xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
212 xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
213 numVpOuts++;
214 usedOutputSlots |= (1 << vpOutSlot);
215 }
216 else {
217 #if 0 /*debug*/
218 printf("VP output %d not used by FP\n", outAttr);
219 #endif
220 }
221 }
222 else if (outAttr == VERT_RESULT_PSIZ)
223 emitPntSize = GL_TRUE;
224 else if (outAttr == VERT_RESULT_BFC0)
225 emitBFC0 = GL_TRUE;
226 else if (outAttr == VERT_RESULT_BFC1)
227 emitBFC1 = GL_TRUE;
228 }
229 #if 0 /*debug*/
230 printf("assign vp output_to_slot[%d] = %d\n", outAttr,
231 xvp->output_to_slot[outAttr]);
232 #endif
233 }
234
235 /* must do these last */
236 if (emitPntSize) {
237 GLuint slot = numVpOuts++;
238 xvp->output_to_slot[VERT_RESULT_PSIZ] = slot;
239 xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
240 xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
241 usedOutputSlots |= (1 << slot);
242 }
243 if (emitBFC0) {
244 GLuint slot = numVpOuts++;
245 xvp->output_to_slot[VERT_RESULT_BFC0] = slot;
246 xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
247 xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
248 usedOutputSlots |= (1 << slot);
249 }
250 if (emitBFC1) {
251 GLuint slot = numVpOuts++;
252 xvp->output_to_slot[VERT_RESULT_BFC1] = slot;
253 xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
254 xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
255 usedOutputSlots |= (1 << slot);
256 }
257
258 /* build usedGenerics mask */
259 usedGenerics = 0x0;
260 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
261 if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
262 usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]);
263 }
264 }
265
266 /* For each vertex program output that doesn't match up to a fragment
267 * program input, map the vertex program output to a free slot and
268 * free generic attribute.
269 */
270 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
271 if (outputsWritten & (1 << outAttr)) {
272 if (xvp->output_to_slot[outAttr] == UNUSED) {
273 GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1;
274 GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1;
275 usedGenerics |= (1 << freeGeneric);
276 usedOutputSlots |= (1 << freeSlot);
277 xvp->output_to_slot[outAttr] = freeSlot;
278 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
279 xvp->output_to_semantic_index[outAttr] = freeGeneric;
280 }
281 }
282
283 #if 0 /*debug*/
284 printf("vp output_to_slot[%d] = %d\n", outAttr,
285 xvp->output_to_slot[outAttr]);
286 #endif
287 }
288
289 st_translate_vertex_program(st, stvp, xvp->output_to_slot,
290 xvp->output_to_semantic_name,
291 xvp->output_to_semantic_index);
292
293 xvp->vp = stvp;
294
295 /* translated VP is up to date now */
296 xvp->serialNo = stvp->serialNo;
297 }
298
299 return xvp;
300 }
301
302
303 void
304 st_free_translated_vertex_programs(struct st_context *st,
305 struct translated_vertex_program *xvp)
306 {
307 struct translated_vertex_program *next;
308
309 while (xvp) {
310 next = xvp->next;
311 _mesa_free(xvp);
312 xvp = next;
313 }
314 }
315
316
317 static void *
318 get_passthrough_fs(struct st_context *st)
319 {
320 if (!st->passthrough_fs) {
321 st->passthrough_fs =
322 util_make_fragment_passthrough_shader(st->pipe);
323 }
324
325 return st->passthrough_fs;
326 }
327
328
329 static void
330 update_linkage( struct st_context *st )
331 {
332 struct st_vertex_program *stvp;
333 struct st_fragment_program *stfp;
334 struct translated_vertex_program *xvp;
335
336 /* find active shader and params -- Should be covered by
337 * ST_NEW_VERTEX_PROGRAM
338 */
339 assert(st->ctx->VertexProgram._Current);
340 stvp = st_vertex_program(st->ctx->VertexProgram._Current);
341 assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
342
343 assert(st->ctx->FragmentProgram._Current);
344 stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
345 assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
346
347 xvp = find_translated_vp(st, stvp, stfp);
348
349 st_reference_vertprog(st, &st->vp, stvp);
350 st_reference_fragprog(st, &st->fp, stfp);
351
352 cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
353
354 if (st->missing_textures) {
355 /* use a pass-through frag shader that uses no textures */
356 void *fs = get_passthrough_fs(st);
357 cso_set_fragment_shader_handle(st->cso_context, fs);
358 }
359 else {
360 cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
361 }
362
363 st->vertex_result_to_slot = xvp->output_to_slot;
364 }
365
366
367 const struct st_tracked_state st_update_shader = {
368 "st_update_shader", /* name */
369 { /* dirty */
370 0, /* mesa */
371 ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM /* st */
372 },
373 update_linkage /* update */
374 };