• 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 "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