Fix problems with vertex shaders and the private draw module.
[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
43 #include "pipe/p_context.h"
44 #include "pipe/p_shader_tokens.h"
45
46 #include "pipe/cso_cache/cso_cache.h"
47
48 #include "st_context.h"
49 #include "st_cache.h"
50 #include "st_atom.h"
51 #include "st_program.h"
52 #include "st_atom_shader.h"
53 #include "st_mesa_to_tgsi.h"
54
55
56 /**
57 * This represents a vertex program, especially translated to match
58 * the inputs of a particular fragment shader.
59 */
60 struct translated_vertex_program
61 {
62 struct st_vertex_program *master;
63
64 /** The fragment shader "signature" this vertex shader is meant for: */
65 GLbitfield frag_inputs;
66
67 /** Compared against master vertex program's serialNo: */
68 GLuint serialNo;
69
70 /** Maps VERT_RESULT_x to slot */
71 GLuint output_to_slot[VERT_RESULT_MAX];
72
73 /** The program in TGSI format */
74 struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
75
76 /** Pointer to the translated vertex program */
77 struct st_vertex_program *vp;
78
79 struct translated_vertex_program *next; /**< next in linked list */
80 };
81
82
83
84 /**
85 * Free data hanging off the st vert prog.
86 */
87 void
88 st_remove_vertex_program(struct st_context *st, struct st_vertex_program *stvp)
89 {
90 /* no-op, for now? */
91 }
92
93
94 /**
95 * Free data hanging off the st frag prog.
96 */
97 void
98 st_remove_fragment_program(struct st_context *st,
99 struct st_fragment_program *stfp)
100 {
101 struct translated_vertex_program *xvp, *next;
102
103 for (xvp = stfp->vertex_programs; xvp; xvp = next) {
104 next = xvp->next;
105 /* XXX free xvp->vs */
106 free(xvp);
107 }
108 }
109
110
111
112 /**
113 * Given a vertex program output attribute, return the corresponding
114 * fragment program input attribute.
115 * \return -1 for vertex outputs that have no corresponding fragment input
116 */
117 static GLint
118 vp_out_to_fp_in(GLuint vertResult)
119 {
120 if (vertResult >= VERT_RESULT_TEX0 &&
121 vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
122 return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
123
124 if (vertResult >= VERT_RESULT_VAR0 &&
125 vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
126 return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
127
128 switch (vertResult) {
129 case VERT_RESULT_HPOS:
130 return FRAG_ATTRIB_WPOS;
131 case VERT_RESULT_COL0:
132 return FRAG_ATTRIB_COL0;
133 case VERT_RESULT_COL1:
134 return FRAG_ATTRIB_COL1;
135 case VERT_RESULT_FOGC:
136 return FRAG_ATTRIB_FOGC;
137 default:
138 /* Back-face colors, edge flags, etc */
139 return -1;
140 }
141 }
142
143
144 /**
145 * Find a translated vertex program that corresponds to stvp and
146 * has outputs matched to stfp's inputs.
147 * This performs vertex and fragment translation (to TGSI) when needed.
148 */
149 static struct translated_vertex_program *
150 find_translated_vp(struct st_context *st,
151 struct st_vertex_program *stvp,
152 struct st_fragment_program *stfp)
153 {
154 static const GLuint UNUSED = ~0;
155 struct translated_vertex_program *xvp;
156 const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
157
158 /*
159 * Translate fragment program if needed.
160 */
161 if (!stfp->fs) {
162 GLuint inAttr, numIn = 0;
163
164 for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
165 if (fragInputsRead & (1 << inAttr)) {
166 stfp->input_to_slot[inAttr] = numIn;
167 numIn++;
168 }
169 else {
170 stfp->input_to_slot[inAttr] = UNUSED;
171 }
172 }
173
174 stfp->num_input_slots = numIn;
175
176 assert(stfp->Base.Base.NumInstructions > 1);
177
178 (void) st_translate_fragment_program(st, stfp,
179 stfp->input_to_slot,
180 stfp->tokens,
181 ST_MAX_SHADER_TOKENS);
182 assert(stfp->fs);
183 }
184
185
186 /* See if we've got a translated vertex program whose outputs match
187 * the fragment program's inputs.
188 * XXX This could be a hash lookup, using InputsRead as the key.
189 */
190 for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
191 if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
192 break;
193 }
194 }
195
196 /* No? Allocate translated vp object now */
197 if (!xvp) {
198 xvp = CALLOC_STRUCT(translated_vertex_program);
199 xvp->frag_inputs = fragInputsRead;
200 xvp->master = stvp;
201
202 xvp->next = stfp->vertex_programs;
203 stfp->vertex_programs = xvp;
204 }
205
206 /* See if we need to translate vertex program to TGSI form */
207 if (xvp->serialNo != stvp->serialNo) {
208 GLuint outAttr, dummySlot;
209 const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
210 GLuint numVpOuts = 0;
211
212 /* Compute mapping of vertex program outputs to slots, which depends
213 * on the fragment program's input->slot mapping.
214 */
215 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
216 /* set default: */
217 xvp->output_to_slot[outAttr] = UNUSED;
218
219 if (outAttr == VERT_RESULT_HPOS) {
220 /* always put xformed position into slot zero */
221 xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
222 numVpOuts++;
223 }
224 else if (outputsWritten & (1 << outAttr)) {
225 /* see if the frag prog wants this vert output */
226 GLint fpInAttrib = vp_out_to_fp_in(outAttr);
227 if (fpInAttrib >= 0) {
228 GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
229 GLuint vpOutSlot = stfp->fs->state.input_map[fpInSlot];
230 xvp->output_to_slot[outAttr] = vpOutSlot;
231 numVpOuts++;
232 }
233 else if (outAttr == VERT_RESULT_PSIZ ||
234 outAttr == VERT_RESULT_BFC0 ||
235 outAttr == VERT_RESULT_BFC1) {
236 /* backface colors go into last slots */
237 xvp->output_to_slot[outAttr] = numVpOuts++;
238 }
239 }
240 /*
241 printf("output_to_slot[%d] = %d\n", outAttr,
242 xvp->output_to_slot[outAttr]);
243 */
244 }
245
246 /* Unneeded vertex program outputs will go to this slot.
247 * We could use this info to do dead code elimination in the
248 * vertex program.
249 */
250 dummySlot = stfp->num_input_slots;
251
252 /* Map vert program outputs that aren't used to the dummy slot */
253 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
254 if (outputsWritten & (1 << outAttr)) {
255 if (xvp->output_to_slot[outAttr] == UNUSED)
256 xvp->output_to_slot[outAttr] = dummySlot;
257 }
258 }
259
260 assert(stvp->Base.Base.NumInstructions > 1);
261
262 st_translate_vertex_program(st, stvp,
263 xvp->output_to_slot,
264 xvp->tokens,
265 ST_MAX_SHADER_TOKENS);
266
267 assert(stvp->cso);
268 xvp->vp = stvp;
269
270 /* translated VP is up to date now */
271 xvp->serialNo = stvp->serialNo;
272 }
273
274 return xvp;
275 }
276
277
278 static void
279 update_linkage( struct st_context *st )
280 {
281 struct st_vertex_program *stvp;
282 struct st_fragment_program *stfp;
283 struct translated_vertex_program *xvp;
284
285 /* find active shader and params -- Should be covered by
286 * ST_NEW_VERTEX_PROGRAM
287 */
288 assert(st->ctx->VertexProgram._Current);
289 stvp = st_vertex_program(st->ctx->VertexProgram._Current);
290
291 assert(st->ctx->FragmentProgram._Current);
292 stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
293
294 xvp = find_translated_vp(st, stvp, stfp);
295
296 st->vp = stvp;
297 st->state.vs = xvp->vp;
298 st->pipe->bind_vs_state(st->pipe, st->state.vs->cso->data);
299
300 st->fp = stfp;
301 st->state.fs = stfp->fs;
302 st->pipe->bind_fs_state(st->pipe, st->state.fs->data);
303
304 st->vertex_result_to_slot = xvp->output_to_slot;
305 }
306
307
308 const struct st_tracked_state st_update_shader = {
309 .name = "st_update_shader",
310 .dirty = {
311 .mesa = 0,
312 .st = ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM
313 },
314 .update = update_linkage
315 };