Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
4565 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 "util/u_math.h"
29
#include "util/u_memory.h"
30
#include "util/u_prim.h"
31
#include "draw/draw_context.h"
32
#include "draw/draw_vbuf.h"
33
#include "draw/draw_vertex.h"
34
#include "draw/draw_prim_assembler.h"
35
#include "draw/draw_pt.h"
36
#include "draw/draw_vs.h"
37
#include "draw/draw_gs.h"
38
39
40
struct fetch_pipeline_middle_end {
41
struct draw_pt_middle_end base;
42
struct draw_context *draw;
43
44
struct pt_emit *emit;
45
struct pt_so_emit *so_emit;
46
struct pt_fetch *fetch;
47
struct pt_post_vs *post_vs;
48
49
unsigned vertex_data_offset;
50
unsigned vertex_size;
51
unsigned input_prim;
52
unsigned opt;
53
};
54
55
56
/** cast wrapper */
57
static inline struct fetch_pipeline_middle_end *
58
fetch_pipeline_middle_end(struct draw_pt_middle_end *middle)
59
{
60
return (struct fetch_pipeline_middle_end *) middle;
61
}
62
63
64
/**
65
* Prepare/validate middle part of the vertex pipeline.
66
* NOTE: if you change this function, also look at the LLVM
67
* function llvm_middle_end_prepare() for similar changes.
68
*/
69
static void
70
fetch_pipeline_prepare(struct draw_pt_middle_end *middle,
71
unsigned prim,
72
unsigned opt,
73
unsigned *max_vertices)
74
{
75
struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
76
struct draw_context *draw = fpme->draw;
77
struct draw_vertex_shader *vs = draw->vs.vertex_shader;
78
struct draw_geometry_shader *gs = draw->gs.geometry_shader;
79
unsigned i;
80
unsigned instance_id_index = ~0;
81
const unsigned gs_out_prim = (gs ? gs->output_primitive :
82
u_assembled_prim(prim));
83
unsigned nr_vs_outputs = draw_total_vs_outputs(draw);
84
unsigned nr = MAX2(vs->info.num_inputs, nr_vs_outputs);
85
unsigned point_clip = draw->rasterizer->fill_front == PIPE_POLYGON_MODE_POINT ||
86
gs_out_prim == PIPE_PRIM_POINTS;
87
88
if (gs) {
89
nr = MAX2(nr, gs->info.num_outputs + 1);
90
}
91
92
/* Scan for instanceID system value.
93
*/
94
for (i = 0; i < vs->info.num_inputs; i++) {
95
if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
96
instance_id_index = i;
97
break;
98
}
99
}
100
101
fpme->input_prim = prim;
102
fpme->opt = opt;
103
104
/* Always leave room for the vertex header whether we need it or
105
* not. It's hard to get rid of it in particular because of the
106
* viewport code in draw_pt_post_vs.c.
107
*/
108
fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
109
110
draw_pt_fetch_prepare( fpme->fetch,
111
vs->info.num_inputs,
112
fpme->vertex_size,
113
instance_id_index );
114
draw_pt_post_vs_prepare( fpme->post_vs,
115
draw->clip_xy,
116
draw->clip_z,
117
draw->clip_user,
118
point_clip ? draw->guard_band_points_xy :
119
draw->guard_band_xy,
120
draw->bypass_viewport,
121
draw->rasterizer->clip_halfz,
122
(draw->vs.edgeflag_output ? TRUE : FALSE) );
123
124
draw_pt_so_emit_prepare( fpme->so_emit, FALSE );
125
126
if (!(opt & PT_PIPELINE)) {
127
draw_pt_emit_prepare( fpme->emit,
128
gs_out_prim,
129
max_vertices );
130
131
*max_vertices = MAX2( *max_vertices, 4096 );
132
}
133
else {
134
/* limit max fetches by limiting max_vertices */
135
*max_vertices = 4096;
136
}
137
138
/* No need to prepare the shader.
139
*/
140
vs->prepare(vs, draw);
141
142
/* Make sure that the vertex size didn't change at any point above */
143
assert(nr_vs_outputs == draw_total_vs_outputs(draw));
144
}
145
146
147
static void
148
fetch_pipeline_bind_parameters(struct draw_pt_middle_end *middle)
149
{
150
/* No-op since the vertex shader executor and drawing pipeline
151
* just grab the constants, viewport, etc. from the draw context state.
152
*/
153
}
154
155
156
static void fetch( struct pt_fetch *fetch,
157
const struct draw_fetch_info *fetch_info,
158
char *output)
159
{
160
if (fetch_info->linear) {
161
draw_pt_fetch_run_linear( fetch,
162
fetch_info->start,
163
fetch_info->count,
164
output );
165
}
166
else {
167
draw_pt_fetch_run( fetch,
168
fetch_info->elts,
169
fetch_info->count,
170
output );
171
}
172
}
173
174
175
static void pipeline(struct fetch_pipeline_middle_end *fpme,
176
const struct draw_vertex_info *vert_info,
177
const struct draw_prim_info *prim_info)
178
{
179
if (prim_info->linear)
180
draw_pipeline_run_linear( fpme->draw,
181
vert_info,
182
prim_info);
183
else
184
draw_pipeline_run( fpme->draw,
185
vert_info,
186
prim_info );
187
}
188
189
190
static void
191
emit(struct pt_emit *emit,
192
const struct draw_vertex_info *vert_info,
193
const struct draw_prim_info *prim_info)
194
{
195
if (prim_info->linear) {
196
draw_pt_emit_linear(emit, vert_info, prim_info);
197
}
198
else {
199
draw_pt_emit(emit, vert_info, prim_info);
200
}
201
}
202
203
204
static void
205
draw_vertex_shader_run(struct draw_vertex_shader *vshader,
206
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
207
unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
208
const struct draw_fetch_info *fetch_info,
209
const struct draw_vertex_info *input_verts,
210
struct draw_vertex_info *output_verts)
211
{
212
output_verts->vertex_size = input_verts->vertex_size;
213
output_verts->stride = input_verts->vertex_size;
214
output_verts->count = input_verts->count;
215
output_verts->verts =
216
(struct vertex_header *)MALLOC(output_verts->vertex_size *
217
align(output_verts->count, 4) +
218
DRAW_EXTRA_VERTICES_PADDING);
219
220
vshader->run_linear(vshader,
221
(const float (*)[4])input_verts->verts->data,
222
( float (*)[4])output_verts->verts->data,
223
constants,
224
const_size,
225
input_verts->count,
226
input_verts->vertex_size,
227
input_verts->vertex_size,
228
fetch_info->elts);
229
}
230
231
232
static void
233
fetch_pipeline_generic(struct draw_pt_middle_end *middle,
234
const struct draw_fetch_info *fetch_info,
235
const struct draw_prim_info *in_prim_info)
236
{
237
struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
238
struct draw_context *draw = fpme->draw;
239
struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
240
struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
241
struct draw_prim_info gs_prim_info[TGSI_MAX_VERTEX_STREAMS];
242
struct draw_vertex_info fetched_vert_info;
243
struct draw_vertex_info vs_vert_info;
244
struct draw_vertex_info gs_vert_info[TGSI_MAX_VERTEX_STREAMS];
245
struct draw_vertex_info *vert_info;
246
struct draw_prim_info ia_prim_info;
247
struct draw_vertex_info ia_vert_info;
248
const struct draw_prim_info *prim_info = in_prim_info;
249
boolean free_prim_info = FALSE;
250
unsigned opt = fpme->opt;
251
int num_vertex_streams = 1;
252
253
fetched_vert_info.count = fetch_info->count;
254
fetched_vert_info.vertex_size = fpme->vertex_size;
255
fetched_vert_info.stride = fpme->vertex_size;
256
fetched_vert_info.verts =
257
(struct vertex_header *)MALLOC(fpme->vertex_size *
258
align(fetch_info->count, 4) +
259
DRAW_EXTRA_VERTICES_PADDING);
260
if (!fetched_vert_info.verts) {
261
assert(0);
262
return;
263
}
264
if (draw->collect_statistics) {
265
draw->statistics.ia_vertices += prim_info->count;
266
draw->statistics.ia_primitives +=
267
u_decomposed_prims_for_vertices(prim_info->prim, fetch_info->count);
268
draw->statistics.vs_invocations += fetch_info->count;
269
}
270
271
/* Fetch into our vertex buffer.
272
*/
273
fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );
274
275
vert_info = &fetched_vert_info;
276
277
/* Run the shader, note that this overwrites the data[] parts of
278
* the pipeline verts.
279
* Need fetch info to get vertex id correct.
280
*/
281
if (fpme->opt & PT_SHADE) {
282
draw_vertex_shader_run(vshader,
283
draw->pt.user.vs_constants,
284
draw->pt.user.vs_constants_size,
285
fetch_info,
286
vert_info,
287
&vs_vert_info);
288
289
FREE(vert_info->verts);
290
vert_info = &vs_vert_info;
291
}
292
293
/* Finished with fetch:
294
*/
295
fetch_info = NULL;
296
297
if ((fpme->opt & PT_SHADE) && gshader) {
298
draw_geometry_shader_run(gshader,
299
draw->pt.user.gs_constants,
300
draw->pt.user.gs_constants_size,
301
vert_info,
302
prim_info,
303
&vshader->info,
304
gs_vert_info,
305
gs_prim_info);
306
307
FREE(vert_info->verts);
308
vert_info = &gs_vert_info[0];
309
prim_info = &gs_prim_info[0];
310
num_vertex_streams = gshader->num_vertex_streams;
311
312
/*
313
* pt emit can only handle ushort number of vertices (see
314
* render->allocate_vertices).
315
* vsplit guarantees there's never more than 4096, however GS can
316
* easily blow this up (by a factor of 256 (or even 1024) max).
317
*/
318
if (vert_info->count > 65535) {
319
opt |= PT_PIPELINE;
320
}
321
} else {
322
if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
323
draw_prim_assembler_run(draw, prim_info, vert_info,
324
&ia_prim_info, &ia_vert_info);
325
326
if (ia_vert_info.count) {
327
FREE(vert_info->verts);
328
vert_info = &ia_vert_info;
329
prim_info = &ia_prim_info;
330
free_prim_info = TRUE;
331
}
332
}
333
}
334
if (prim_info->count == 0) {
335
debug_printf("GS/IA didn't emit any vertices!\n");
336
337
FREE(vert_info->verts);
338
if (free_prim_info) {
339
FREE(prim_info->primitive_lengths);
340
}
341
return;
342
}
343
344
345
/* Stream output needs to be done before clipping.
346
*
347
* XXX: Stream output surely needs to respect the prim_info->elt
348
* lists.
349
*/
350
draw_pt_so_emit( fpme->so_emit, num_vertex_streams, vert_info, prim_info );
351
352
draw_stats_clipper_primitives(draw, prim_info);
353
354
/*
355
* if there's no position, need to stop now, or the latter stages
356
* will try to access non-existent position output.
357
*/
358
if (draw_current_shader_position_output(draw) != -1) {
359
360
if (draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info ))
361
{
362
opt |= PT_PIPELINE;
363
}
364
365
/* Do we need to run the pipeline?
366
*/
367
if (opt & PT_PIPELINE) {
368
pipeline( fpme, vert_info, prim_info );
369
}
370
else {
371
emit( fpme->emit, vert_info, prim_info );
372
}
373
}
374
FREE(vert_info->verts);
375
if (free_prim_info) {
376
FREE(prim_info->primitive_lengths);
377
}
378
}
379
380
381
static inline unsigned
382
prim_type(unsigned prim, unsigned flags)
383
{
384
if (flags & DRAW_LINE_LOOP_AS_STRIP)
385
return PIPE_PRIM_LINE_STRIP;
386
else
387
return prim;
388
}
389
390
391
static void
392
fetch_pipeline_run(struct draw_pt_middle_end *middle,
393
const unsigned *fetch_elts,
394
unsigned fetch_count,
395
const ushort *draw_elts,
396
unsigned draw_count,
397
unsigned prim_flags)
398
{
399
struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
400
struct draw_fetch_info fetch_info;
401
struct draw_prim_info prim_info;
402
403
fetch_info.linear = FALSE;
404
fetch_info.start = 0;
405
fetch_info.elts = fetch_elts;
406
fetch_info.count = fetch_count;
407
408
prim_info.linear = FALSE;
409
prim_info.start = 0;
410
prim_info.count = draw_count;
411
prim_info.elts = draw_elts;
412
prim_info.prim = prim_type(fpme->input_prim, prim_flags);
413
prim_info.flags = prim_flags;
414
prim_info.primitive_count = 1;
415
prim_info.primitive_lengths = &draw_count;
416
417
fetch_pipeline_generic( middle, &fetch_info, &prim_info );
418
}
419
420
421
static void
422
fetch_pipeline_linear_run(struct draw_pt_middle_end *middle,
423
unsigned start,
424
unsigned count,
425
unsigned prim_flags)
426
{
427
struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
428
struct draw_fetch_info fetch_info;
429
struct draw_prim_info prim_info;
430
431
fetch_info.linear = TRUE;
432
fetch_info.start = start;
433
fetch_info.count = count;
434
fetch_info.elts = NULL;
435
436
prim_info.linear = TRUE;
437
prim_info.start = 0;
438
prim_info.count = count;
439
prim_info.elts = NULL;
440
prim_info.prim = prim_type(fpme->input_prim, prim_flags);
441
prim_info.flags = prim_flags;
442
prim_info.primitive_count = 1;
443
prim_info.primitive_lengths = &count;
444
445
fetch_pipeline_generic( middle, &fetch_info, &prim_info );
446
}
447
448
449
450
static boolean
451
fetch_pipeline_linear_run_elts(struct draw_pt_middle_end *middle,
452
unsigned start,
453
unsigned count,
454
const ushort *draw_elts,
455
unsigned draw_count,
456
unsigned prim_flags )
457
{
458
struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
459
struct draw_fetch_info fetch_info;
460
struct draw_prim_info prim_info;
461
462
fetch_info.linear = TRUE;
463
fetch_info.start = start;
464
fetch_info.count = count;
465
fetch_info.elts = NULL;
466
467
prim_info.linear = FALSE;
468
prim_info.start = 0;
469
prim_info.count = draw_count;
470
prim_info.elts = draw_elts;
471
prim_info.prim = prim_type(fpme->input_prim, prim_flags);
472
prim_info.flags = prim_flags;
473
prim_info.primitive_count = 1;
474
prim_info.primitive_lengths = &draw_count;
475
476
fetch_pipeline_generic( middle, &fetch_info, &prim_info );
477
478
return TRUE;
479
}
480
481
482
static void
483
fetch_pipeline_finish( struct draw_pt_middle_end *middle )
484
{
485
/* nothing to do */
486
}
487
488
489
static void
490
fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
491
{
492
struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
493
494
if (fpme->fetch)
495
draw_pt_fetch_destroy( fpme->fetch );
496
497
if (fpme->emit)
498
draw_pt_emit_destroy( fpme->emit );
499
500
if (fpme->so_emit)
501
draw_pt_so_emit_destroy( fpme->so_emit );
502
503
if (fpme->post_vs)
504
draw_pt_post_vs_destroy( fpme->post_vs );
505
506
FREE(middle);
507
}
508
509
510
struct draw_pt_middle_end *
511
draw_pt_fetch_pipeline_or_emit(struct draw_context *draw)
512
{
513
struct fetch_pipeline_middle_end *fpme =
514
CALLOC_STRUCT( fetch_pipeline_middle_end );
515
if (!fpme)
516
goto fail;
517
518
fpme->base.prepare = fetch_pipeline_prepare;
519
fpme->base.bind_parameters = fetch_pipeline_bind_parameters;
520
fpme->base.run = fetch_pipeline_run;
521
fpme->base.run_linear = fetch_pipeline_linear_run;
522
fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
523
fpme->base.finish = fetch_pipeline_finish;
524
fpme->base.destroy = fetch_pipeline_destroy;
525
526
fpme->draw = draw;
527
528
fpme->fetch = draw_pt_fetch_create( draw );
529
if (!fpme->fetch)
530
goto fail;
531
532
fpme->post_vs = draw_pt_post_vs_create( draw );
533
if (!fpme->post_vs)
534
goto fail;
535
536
fpme->emit = draw_pt_emit_create( draw );
537
if (!fpme->emit)
538
goto fail;
539
540
fpme->so_emit = draw_pt_so_emit_create( draw );
541
if (!fpme->so_emit)
542
goto fail;
543
544
return &fpme->base;
545
546
fail:
547
if (fpme)
548
fetch_pipeline_destroy( &fpme->base );
549
550
return NULL;
551
}
552
553