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 #include "sp_context.h"
29 #include "sp_state.h"
30 #include "sp_fs.h"
31 #include "sp_texture.h"
32
33 #include "pipe/p_defines.h"
34 #include "util/u_memory.h"
35 #include "util/u_inlines.h"
36 #include "util/u_pstipple.h"
37 #include "draw/draw_context.h"
38 #include "draw/draw_vs.h"
39 #include "draw/draw_gs.h"
40 #include "tgsi/tgsi_dump.h"
41 #include "tgsi/tgsi_scan.h"
42 #include "tgsi/tgsi_parse.h"
43
44
45 /**
46 * Create a new fragment shader variant.
47 */
48 static struct sp_fragment_shader_variant *
create_fs_variant(struct softpipe_context * softpipe,struct sp_fragment_shader * fs,const struct sp_fragment_shader_variant_key * key)49 create_fs_variant(struct softpipe_context *softpipe,
50 struct sp_fragment_shader *fs,
51 const struct sp_fragment_shader_variant_key *key)
52 {
53 struct sp_fragment_shader_variant *var;
54 struct pipe_shader_state *curfs = &fs->shader;
55
56 /* codegen, create variant object */
57 var = softpipe_create_fs_variant_exec(softpipe);
58
59 if (var) {
60 var->key = *key;
61
62 #if DO_PSTIPPLE_IN_HELPER_MODULE
63 if (key->polygon_stipple) {
64 /* get new shader that implements polygon stippling */
65 var->tokens =
66 util_pstipple_create_fragment_shader(curfs->tokens,
67 &var->stipple_sampler_unit, 0,
68 TGSI_FILE_INPUT);
69 }
70 else
71 #endif
72 {
73 var->tokens = tgsi_dup_tokens(curfs->tokens);
74 var->stipple_sampler_unit = 0;
75 }
76
77 tgsi_scan_shader(var->tokens, &var->info);
78
79 /* See comments elsewhere about draw fragment shaders */
80 #if 0
81 /* draw's fs state */
82 var->draw_shader = draw_create_fragment_shader(softpipe->draw,
83 &fs->shader);
84 if (!var->draw_shader) {
85 var->delete(var);
86 FREE((void *) var->tokens);
87 return NULL;
88 }
89 #endif
90
91 /* insert variant into linked list */
92 var->next = fs->variants;
93 fs->variants = var;
94 }
95
96 return var;
97 }
98
99
100 struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context * sp,struct sp_fragment_shader * fs,const struct sp_fragment_shader_variant_key * key)101 softpipe_find_fs_variant(struct softpipe_context *sp,
102 struct sp_fragment_shader *fs,
103 const struct sp_fragment_shader_variant_key *key)
104 {
105 struct sp_fragment_shader_variant *var;
106
107 for (var = fs->variants; var; var = var->next) {
108 if (memcmp(&var->key, key, sizeof(*key)) == 0) {
109 /* found it */
110 return var;
111 }
112 }
113
114 return create_fs_variant(sp, fs, key);
115 }
116
117
118 static void *
softpipe_create_fs_state(struct pipe_context * pipe,const struct pipe_shader_state * templ)119 softpipe_create_fs_state(struct pipe_context *pipe,
120 const struct pipe_shader_state *templ)
121 {
122 struct softpipe_context *softpipe = softpipe_context(pipe);
123 struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
124
125 /* debug */
126 if (softpipe->dump_fs)
127 tgsi_dump(templ->tokens, 0);
128
129 /* we need to keep a local copy of the tokens */
130 state->shader.tokens = tgsi_dup_tokens(templ->tokens);
131
132 /* draw's fs state */
133 state->draw_shader = draw_create_fragment_shader(softpipe->draw,
134 &state->shader);
135 if (!state->draw_shader) {
136 tgsi_free_tokens(state->shader.tokens);
137 FREE(state);
138 return NULL;
139 }
140
141 return state;
142 }
143
144
145 static void
softpipe_bind_fs_state(struct pipe_context * pipe,void * fs)146 softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
147 {
148 struct softpipe_context *softpipe = softpipe_context(pipe);
149 struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
150
151 if (softpipe->fs == fs)
152 return;
153
154 draw_flush(softpipe->draw);
155
156 softpipe->fs = fs;
157
158 /* This depends on the current fragment shader and must always be
159 * re-validated before use.
160 */
161 softpipe->fs_variant = NULL;
162
163 if (state)
164 draw_bind_fragment_shader(softpipe->draw,
165 state->draw_shader);
166 else
167 draw_bind_fragment_shader(softpipe->draw, NULL);
168
169 softpipe->dirty |= SP_NEW_FS;
170 }
171
172
173 static void
softpipe_delete_fs_state(struct pipe_context * pipe,void * fs)174 softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
175 {
176 struct softpipe_context *softpipe = softpipe_context(pipe);
177 struct sp_fragment_shader *state = fs;
178 struct sp_fragment_shader_variant *var, *next_var;
179
180 assert(fs != softpipe->fs);
181
182 /* delete variants */
183 for (var = state->variants; var; var = next_var) {
184 next_var = var->next;
185
186 assert(var != softpipe->fs_variant);
187
188 /* See comments elsewhere about draw fragment shaders */
189 #if 0
190 draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
191 #endif
192
193 var->delete(var, softpipe->fs_machine);
194 }
195
196 draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
197
198 tgsi_free_tokens(state->shader.tokens);
199 FREE(state);
200 }
201
202
203 static void *
softpipe_create_vs_state(struct pipe_context * pipe,const struct pipe_shader_state * templ)204 softpipe_create_vs_state(struct pipe_context *pipe,
205 const struct pipe_shader_state *templ)
206 {
207 struct softpipe_context *softpipe = softpipe_context(pipe);
208 struct sp_vertex_shader *state;
209
210 state = CALLOC_STRUCT(sp_vertex_shader);
211 if (!state)
212 goto fail;
213
214 /* copy shader tokens, the ones passed in will go away.
215 */
216 state->shader.tokens = tgsi_dup_tokens(templ->tokens);
217 if (state->shader.tokens == NULL)
218 goto fail;
219
220 state->draw_data = draw_create_vertex_shader(softpipe->draw, templ);
221 if (state->draw_data == NULL)
222 goto fail;
223
224 state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
225
226 return state;
227
228 fail:
229 if (state) {
230 tgsi_free_tokens(state->shader.tokens);
231 FREE( state->draw_data );
232 FREE( state );
233 }
234 return NULL;
235 }
236
237
238 static void
softpipe_bind_vs_state(struct pipe_context * pipe,void * vs)239 softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
240 {
241 struct softpipe_context *softpipe = softpipe_context(pipe);
242
243 softpipe->vs = (struct sp_vertex_shader *) vs;
244
245 draw_bind_vertex_shader(softpipe->draw,
246 (softpipe->vs ? softpipe->vs->draw_data : NULL));
247
248 softpipe->dirty |= SP_NEW_VS;
249 }
250
251
252 static void
softpipe_delete_vs_state(struct pipe_context * pipe,void * vs)253 softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
254 {
255 struct softpipe_context *softpipe = softpipe_context(pipe);
256
257 struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;
258
259 draw_delete_vertex_shader(softpipe->draw, state->draw_data);
260 tgsi_free_tokens(state->shader.tokens);
261 FREE( state );
262 }
263
264
265 static void *
softpipe_create_gs_state(struct pipe_context * pipe,const struct pipe_shader_state * templ)266 softpipe_create_gs_state(struct pipe_context *pipe,
267 const struct pipe_shader_state *templ)
268 {
269 struct softpipe_context *softpipe = softpipe_context(pipe);
270 struct sp_geometry_shader *state;
271
272 state = CALLOC_STRUCT(sp_geometry_shader);
273 if (!state)
274 goto fail;
275
276 state->shader = *templ;
277
278 if (templ->tokens) {
279 /* debug */
280 if (softpipe->dump_gs)
281 tgsi_dump(templ->tokens, 0);
282
283 /* copy shader tokens, the ones passed in will go away.
284 */
285 state->shader.tokens = tgsi_dup_tokens(templ->tokens);
286 if (state->shader.tokens == NULL)
287 goto fail;
288
289 state->draw_data = draw_create_geometry_shader(softpipe->draw, templ);
290 if (state->draw_data == NULL)
291 goto fail;
292
293 state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
294 }
295
296 return state;
297
298 fail:
299 if (state) {
300 tgsi_free_tokens(state->shader.tokens);
301 FREE( state->draw_data );
302 FREE( state );
303 }
304 return NULL;
305 }
306
307
308 static void
softpipe_bind_gs_state(struct pipe_context * pipe,void * gs)309 softpipe_bind_gs_state(struct pipe_context *pipe, void *gs)
310 {
311 struct softpipe_context *softpipe = softpipe_context(pipe);
312
313 softpipe->gs = (struct sp_geometry_shader *)gs;
314
315 draw_bind_geometry_shader(softpipe->draw,
316 (softpipe->gs ? softpipe->gs->draw_data : NULL));
317
318 softpipe->dirty |= SP_NEW_GS;
319 }
320
321
322 static void
softpipe_delete_gs_state(struct pipe_context * pipe,void * gs)323 softpipe_delete_gs_state(struct pipe_context *pipe, void *gs)
324 {
325 struct softpipe_context *softpipe = softpipe_context(pipe);
326
327 struct sp_geometry_shader *state =
328 (struct sp_geometry_shader *)gs;
329
330 draw_delete_geometry_shader(softpipe->draw,
331 (state) ? state->draw_data : 0);
332
333 tgsi_free_tokens(state->shader.tokens);
334 FREE(state);
335 }
336
337
338 static void
softpipe_set_constant_buffer(struct pipe_context * pipe,enum pipe_shader_type shader,uint index,const struct pipe_constant_buffer * cb)339 softpipe_set_constant_buffer(struct pipe_context *pipe,
340 enum pipe_shader_type shader, uint index,
341 const struct pipe_constant_buffer *cb)
342 {
343 struct softpipe_context *softpipe = softpipe_context(pipe);
344 struct pipe_resource *constants = cb ? cb->buffer : NULL;
345 unsigned size;
346 const void *data;
347
348 assert(shader < PIPE_SHADER_TYPES);
349
350 if (cb && cb->user_buffer) {
351 constants = softpipe_user_buffer_create(pipe->screen,
352 (void *) cb->user_buffer,
353 cb->buffer_size,
354 PIPE_BIND_CONSTANT_BUFFER);
355 }
356
357 size = cb ? cb->buffer_size : 0;
358 data = constants ? softpipe_resource_data(constants) : NULL;
359 if (data)
360 data = (const char *) data + cb->buffer_offset;
361
362 draw_flush(softpipe->draw);
363
364 /* note: reference counting */
365 pipe_resource_reference(&softpipe->constants[shader][index], constants);
366
367 if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
368 draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);
369 }
370
371 softpipe->mapped_constants[shader][index] = data;
372 softpipe->const_buffer_size[shader][index] = size;
373
374 softpipe->dirty |= SP_NEW_CONSTANTS;
375
376 if (cb && cb->user_buffer) {
377 pipe_resource_reference(&constants, NULL);
378 }
379 }
380
381 static void *
softpipe_create_compute_state(struct pipe_context * pipe,const struct pipe_compute_state * templ)382 softpipe_create_compute_state(struct pipe_context *pipe,
383 const struct pipe_compute_state *templ)
384 {
385 struct softpipe_context *softpipe = softpipe_context(pipe);
386 const struct tgsi_token *tokens;
387 struct sp_compute_shader *state;
388 if (templ->ir_type != PIPE_SHADER_IR_TGSI)
389 return NULL;
390
391 tokens = templ->prog;
392 /* debug */
393 if (softpipe->dump_cs)
394 tgsi_dump(tokens, 0);
395
396 state = CALLOC_STRUCT(sp_compute_shader);
397
398 state->shader = *templ;
399 state->tokens = tgsi_dup_tokens(tokens);
400 tgsi_scan_shader(state->tokens, &state->info);
401
402 state->max_sampler = state->info.file_max[TGSI_FILE_SAMPLER];
403
404 return state;
405 }
406
407 static void
softpipe_bind_compute_state(struct pipe_context * pipe,void * cs)408 softpipe_bind_compute_state(struct pipe_context *pipe,
409 void *cs)
410 {
411 struct softpipe_context *softpipe = softpipe_context(pipe);
412 struct sp_compute_shader *state = (struct sp_compute_shader *)cs;
413 if (softpipe->cs == state)
414 return;
415
416 softpipe->cs = state;
417 }
418
419 static void
softpipe_delete_compute_state(struct pipe_context * pipe,void * cs)420 softpipe_delete_compute_state(struct pipe_context *pipe,
421 void *cs)
422 {
423 MAYBE_UNUSED struct softpipe_context *softpipe = softpipe_context(pipe);
424 struct sp_compute_shader *state = (struct sp_compute_shader *)cs;
425
426 assert(softpipe->cs != state);
427 tgsi_free_tokens(state->tokens);
428 FREE(state);
429 }
430
431 void
softpipe_init_shader_funcs(struct pipe_context * pipe)432 softpipe_init_shader_funcs(struct pipe_context *pipe)
433 {
434 pipe->create_fs_state = softpipe_create_fs_state;
435 pipe->bind_fs_state = softpipe_bind_fs_state;
436 pipe->delete_fs_state = softpipe_delete_fs_state;
437
438 pipe->create_vs_state = softpipe_create_vs_state;
439 pipe->bind_vs_state = softpipe_bind_vs_state;
440 pipe->delete_vs_state = softpipe_delete_vs_state;
441
442 pipe->create_gs_state = softpipe_create_gs_state;
443 pipe->bind_gs_state = softpipe_bind_gs_state;
444 pipe->delete_gs_state = softpipe_delete_gs_state;
445
446 pipe->set_constant_buffer = softpipe_set_constant_buffer;
447
448 pipe->create_compute_state = softpipe_create_compute_state;
449 pipe->bind_compute_state = softpipe_bind_compute_state;
450 pipe->delete_compute_state = softpipe_delete_compute_state;
451 }
452