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