• 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       if (debug)
147          nir_print_shader(templ->ir.nir, stderr);
148 
149       shader->tokens = nir_to_tgsi(templ->ir.nir, pipe->screen);
150    } else {
151       assert(templ->type == PIPE_SHADER_IR_TGSI);
152       /* we need to keep a local copy of the tokens */
153       shader->tokens = tgsi_dup_tokens(templ->tokens);
154    }
155 
156    shader->type = PIPE_SHADER_IR_TGSI;
157 
158    shader->stream_output = templ->stream_output;
159 
160    if (debug)
161       tgsi_dump(shader->tokens, 0);
162 
163    softpipe_shader_db(pipe, shader->tokens);
164 }
165 
166 static void *
softpipe_create_fs_state(struct pipe_context * pipe,const struct pipe_shader_state * templ)167 softpipe_create_fs_state(struct pipe_context *pipe,
168                          const struct pipe_shader_state *templ)
169 {
170    struct softpipe_context *softpipe = softpipe_context(pipe);
171    struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
172 
173    softpipe_create_shader_state(pipe, &state->shader, templ,
174                                 sp_debug & SP_DBG_FS);
175 
176    /* draw's fs state */
177    state->draw_shader = draw_create_fragment_shader(softpipe->draw,
178                                                     &state->shader);
179    if (!state->draw_shader) {
180       tgsi_free_tokens(state->shader.tokens);
181       FREE(state);
182       return NULL;
183    }
184 
185    return state;
186 }
187 
188 
189 static void
softpipe_bind_fs_state(struct pipe_context * pipe,void * fs)190 softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
191 {
192    struct softpipe_context *softpipe = softpipe_context(pipe);
193    struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
194 
195    if (softpipe->fs == fs)
196       return;
197 
198    draw_flush(softpipe->draw);
199 
200    softpipe->fs = fs;
201 
202    /* This depends on the current fragment shader and must always be
203     * re-validated before use.
204     */
205    softpipe->fs_variant = NULL;
206 
207    if (state)
208       draw_bind_fragment_shader(softpipe->draw,
209                                 state->draw_shader);
210    else
211       draw_bind_fragment_shader(softpipe->draw, NULL);
212 
213    softpipe->dirty |= SP_NEW_FS;
214 }
215 
216 
217 static void
softpipe_delete_fs_state(struct pipe_context * pipe,void * fs)218 softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
219 {
220    struct softpipe_context *softpipe = softpipe_context(pipe);
221    struct sp_fragment_shader *state = fs;
222    struct sp_fragment_shader_variant *var, *next_var;
223 
224    assert(fs != softpipe->fs);
225 
226    /* delete variants */
227    for (var = state->variants; var; var = next_var) {
228       next_var = var->next;
229 
230       assert(var != softpipe->fs_variant);
231 
232       /* See comments elsewhere about draw fragment shaders */
233 #if 0
234       draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
235 #endif
236 
237       var->delete(var, softpipe->fs_machine);
238    }
239 
240    draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
241 
242    tgsi_free_tokens(state->shader.tokens);
243    FREE(state);
244 }
245 
246 
247 static void *
softpipe_create_vs_state(struct pipe_context * pipe,const struct pipe_shader_state * templ)248 softpipe_create_vs_state(struct pipe_context *pipe,
249                          const struct pipe_shader_state *templ)
250 {
251    struct softpipe_context *softpipe = softpipe_context(pipe);
252    struct sp_vertex_shader *state;
253 
254    state = CALLOC_STRUCT(sp_vertex_shader);
255    if (!state)
256       goto fail;
257 
258    softpipe_create_shader_state(pipe, &state->shader, templ,
259                                 sp_debug & SP_DBG_VS);
260    if (!state->shader.tokens)
261       goto fail;
262 
263    state->draw_data = draw_create_vertex_shader(softpipe->draw, &state->shader);
264    if (state->draw_data == NULL)
265       goto fail;
266 
267    state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
268 
269    return state;
270 
271 fail:
272    if (state) {
273       tgsi_free_tokens(state->shader.tokens);
274       FREE( state->draw_data );
275       FREE( state );
276    }
277    return NULL;
278 }
279 
280 
281 static void
softpipe_bind_vs_state(struct pipe_context * pipe,void * vs)282 softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
283 {
284    struct softpipe_context *softpipe = softpipe_context(pipe);
285 
286    softpipe->vs = (struct sp_vertex_shader *) vs;
287 
288    draw_bind_vertex_shader(softpipe->draw,
289                            (softpipe->vs ? softpipe->vs->draw_data : NULL));
290 
291    softpipe->dirty |= SP_NEW_VS;
292 }
293 
294 
295 static void
softpipe_delete_vs_state(struct pipe_context * pipe,void * vs)296 softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
297 {
298    struct softpipe_context *softpipe = softpipe_context(pipe);
299 
300    struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;
301 
302    draw_delete_vertex_shader(softpipe->draw, state->draw_data);
303    tgsi_free_tokens(state->shader.tokens);
304    FREE( state );
305 }
306 
307 
308 static void *
softpipe_create_gs_state(struct pipe_context * pipe,const struct pipe_shader_state * templ)309 softpipe_create_gs_state(struct pipe_context *pipe,
310                          const struct pipe_shader_state *templ)
311 {
312    struct softpipe_context *softpipe = softpipe_context(pipe);
313    struct sp_geometry_shader *state;
314 
315    state = CALLOC_STRUCT(sp_geometry_shader);
316    if (!state)
317       goto fail;
318 
319    softpipe_create_shader_state(pipe, &state->shader, templ,
320                                 sp_debug & SP_DBG_GS);
321 
322    if (state->shader.tokens) {
323       state->draw_data = draw_create_geometry_shader(softpipe->draw,
324                                                      &state->shader);
325       if (state->draw_data == NULL)
326          goto fail;
327 
328       state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
329    }
330 
331    return state;
332 
333 fail:
334    if (state) {
335       tgsi_free_tokens(state->shader.tokens);
336       FREE( state->draw_data );
337       FREE( state );
338    }
339    return NULL;
340 }
341 
342 
343 static void
softpipe_bind_gs_state(struct pipe_context * pipe,void * gs)344 softpipe_bind_gs_state(struct pipe_context *pipe, void *gs)
345 {
346    struct softpipe_context *softpipe = softpipe_context(pipe);
347 
348    softpipe->gs = (struct sp_geometry_shader *)gs;
349 
350    draw_bind_geometry_shader(softpipe->draw,
351                              (softpipe->gs ? softpipe->gs->draw_data : NULL));
352 
353    softpipe->dirty |= SP_NEW_GS;
354 }
355 
356 
357 static void
softpipe_delete_gs_state(struct pipe_context * pipe,void * gs)358 softpipe_delete_gs_state(struct pipe_context *pipe, void *gs)
359 {
360    struct softpipe_context *softpipe = softpipe_context(pipe);
361 
362    struct sp_geometry_shader *state =
363       (struct sp_geometry_shader *)gs;
364 
365    draw_delete_geometry_shader(softpipe->draw,
366                                (state) ? state->draw_data : 0);
367 
368    tgsi_free_tokens(state->shader.tokens);
369    FREE(state);
370 }
371 
372 
373 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)374 softpipe_set_constant_buffer(struct pipe_context *pipe,
375                              enum pipe_shader_type shader, uint index,
376                              bool take_ownership,
377                              const struct pipe_constant_buffer *cb)
378 {
379    struct softpipe_context *softpipe = softpipe_context(pipe);
380    struct pipe_resource *constants = cb ? cb->buffer : NULL;
381    unsigned size;
382    const void *data;
383 
384    assert(shader < PIPE_SHADER_TYPES);
385 
386    if (cb && cb->user_buffer) {
387       constants = softpipe_user_buffer_create(pipe->screen,
388                                               (void *) cb->user_buffer,
389                                               cb->buffer_size,
390                                               PIPE_BIND_CONSTANT_BUFFER);
391    }
392 
393    size = cb ? cb->buffer_size : 0;
394    data = constants ? softpipe_resource_data(constants) : NULL;
395    if (data)
396       data = (const char *) data + cb->buffer_offset;
397 
398    draw_flush(softpipe->draw);
399 
400    /* note: reference counting */
401    if (take_ownership) {
402       pipe_resource_reference(&softpipe->constants[shader][index], NULL);
403       softpipe->constants[shader][index] = constants;
404    } else {
405       pipe_resource_reference(&softpipe->constants[shader][index], constants);
406    }
407 
408    if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
409       draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);
410    }
411 
412    softpipe->mapped_constants[shader][index] = data;
413    softpipe->const_buffer_size[shader][index] = size;
414 
415    softpipe->dirty |= SP_NEW_CONSTANTS;
416 
417    if (cb && cb->user_buffer) {
418       pipe_resource_reference(&constants, NULL);
419    }
420 }
421 
422 static void *
softpipe_create_compute_state(struct pipe_context * pipe,const struct pipe_compute_state * templ)423 softpipe_create_compute_state(struct pipe_context *pipe,
424                               const struct pipe_compute_state *templ)
425 {
426    struct sp_compute_shader *state = CALLOC_STRUCT(sp_compute_shader);
427 
428    state->shader = *templ;
429 
430    if (templ->ir_type == PIPE_SHADER_IR_NIR) {
431       nir_shader *s = (void *)templ->prog;
432 
433       if (sp_debug & SP_DBG_CS)
434          nir_print_shader(s, stderr);
435 
436       state->tokens = (void *)nir_to_tgsi(s, pipe->screen);
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