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