Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/softpipe/sp_state_shader.c
4570 views
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 *
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 *
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
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
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 *
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
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
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 *
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
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
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 *
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
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
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
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 *
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
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
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
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
501