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