Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/freedreno/freedreno_context.h
4570 views
1
/*
2
* Copyright (C) 2012 Rob Clark <[email protected]>
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
* SOFTWARE.
22
*
23
* Authors:
24
* Rob Clark <[email protected]>
25
*/
26
27
#ifndef FREEDRENO_CONTEXT_H_
28
#define FREEDRENO_CONTEXT_H_
29
30
#include "indices/u_primconvert.h"
31
#include "pipe/p_context.h"
32
#include "util/libsync.h"
33
#include "util/list.h"
34
#include "util/slab.h"
35
#include "util/u_blitter.h"
36
#include "util/u_string.h"
37
#include "util/u_threaded_context.h"
38
#include "util/u_trace.h"
39
40
#include "freedreno_autotune.h"
41
#include "freedreno_gmem.h"
42
#include "freedreno_perfetto.h"
43
#include "freedreno_screen.h"
44
#include "freedreno_util.h"
45
46
#ifdef __cplusplus
47
extern "C" {
48
#endif
49
50
#define BORDER_COLOR_UPLOAD_SIZE (2 * PIPE_MAX_SAMPLERS * BORDERCOLOR_SIZE)
51
52
struct fd_vertex_stateobj;
53
struct fd_batch;
54
55
struct fd_texture_stateobj {
56
struct pipe_sampler_view *textures[PIPE_MAX_SAMPLERS];
57
unsigned num_textures;
58
unsigned valid_textures;
59
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
60
unsigned num_samplers;
61
unsigned valid_samplers;
62
};
63
64
struct fd_program_stateobj {
65
void *vs, *hs, *ds, *gs, *fs;
66
};
67
68
struct fd_constbuf_stateobj {
69
struct pipe_constant_buffer cb[PIPE_MAX_CONSTANT_BUFFERS];
70
uint32_t enabled_mask;
71
};
72
73
struct fd_shaderbuf_stateobj {
74
struct pipe_shader_buffer sb[PIPE_MAX_SHADER_BUFFERS];
75
uint32_t enabled_mask;
76
uint32_t writable_mask;
77
};
78
79
struct fd_shaderimg_stateobj {
80
struct pipe_image_view si[PIPE_MAX_SHADER_IMAGES];
81
uint32_t enabled_mask;
82
};
83
84
struct fd_vertexbuf_stateobj {
85
struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
86
unsigned count;
87
uint32_t enabled_mask;
88
};
89
90
struct fd_vertex_stateobj {
91
struct pipe_vertex_element pipe[PIPE_MAX_ATTRIBS];
92
unsigned num_elements;
93
};
94
95
struct fd_stream_output_target {
96
struct pipe_stream_output_target base;
97
struct pipe_resource *offset_buf;
98
/* stride of the last stream out recorded to this target, for
99
* glDrawTransformFeedback(). */
100
uint32_t stride;
101
};
102
103
struct fd_streamout_stateobj {
104
struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS];
105
/* Bitmask of stream that should be reset. */
106
unsigned reset;
107
108
unsigned num_targets;
109
/* Track offset from vtxcnt for streamout data. This counter
110
* is just incremented by # of vertices on each draw until
111
* reset or new streamout buffer bound.
112
*
113
* When we eventually have GS, the CPU won't actually know the
114
* number of vertices per draw, so I think we'll have to do
115
* something more clever.
116
*/
117
unsigned offsets[PIPE_MAX_SO_BUFFERS];
118
119
/* Pre-a6xx, the maximum number of vertices that could be recorded to this
120
* set of targets with the current vertex shader. a6xx and newer, hardware
121
* queries are used.
122
*/
123
unsigned max_tf_vtx;
124
125
/* Pre-a6xx, the number of verts written to the buffers since the last
126
* Begin. Used for overflow checking for SW queries.
127
*/
128
unsigned verts_written;
129
};
130
131
#define MAX_GLOBAL_BUFFERS 16
132
struct fd_global_bindings_stateobj {
133
struct pipe_resource *buf[MAX_GLOBAL_BUFFERS];
134
uint32_t enabled_mask;
135
};
136
137
/* group together the vertex and vertexbuf state.. for ease of passing
138
* around, and because various internal operations (gmem<->mem, etc)
139
* need their own vertex state:
140
*/
141
struct fd_vertex_state {
142
struct fd_vertex_stateobj *vtx;
143
struct fd_vertexbuf_stateobj vertexbuf;
144
};
145
146
/* global 3d pipeline dirty state: */
147
enum fd_dirty_3d_state {
148
FD_DIRTY_BLEND = BIT(0),
149
FD_DIRTY_RASTERIZER = BIT(1),
150
FD_DIRTY_ZSA = BIT(2),
151
FD_DIRTY_BLEND_COLOR = BIT(3),
152
FD_DIRTY_STENCIL_REF = BIT(4),
153
FD_DIRTY_SAMPLE_MASK = BIT(5),
154
FD_DIRTY_FRAMEBUFFER = BIT(6),
155
FD_DIRTY_STIPPLE = BIT(7),
156
FD_DIRTY_VIEWPORT = BIT(8),
157
FD_DIRTY_VTXSTATE = BIT(9),
158
FD_DIRTY_VTXBUF = BIT(10),
159
FD_DIRTY_MIN_SAMPLES = BIT(11),
160
FD_DIRTY_SCISSOR = BIT(12),
161
FD_DIRTY_STREAMOUT = BIT(13),
162
FD_DIRTY_UCP = BIT(14),
163
FD_DIRTY_PROG = BIT(15),
164
FD_DIRTY_CONST = BIT(16),
165
FD_DIRTY_TEX = BIT(17),
166
FD_DIRTY_IMAGE = BIT(18),
167
FD_DIRTY_SSBO = BIT(19),
168
169
/* only used by a2xx.. possibly can be removed.. */
170
FD_DIRTY_TEXSTATE = BIT(20),
171
172
/* fine grained state changes, for cases where state is not orthogonal
173
* from hw perspective:
174
*/
175
FD_DIRTY_RASTERIZER_DISCARD = BIT(24),
176
FD_DIRTY_BLEND_DUAL = BIT(25),
177
#define NUM_DIRTY_BITS 26
178
179
/* additional flag for state requires updated resource tracking: */
180
FD_DIRTY_RESOURCE = BIT(31),
181
};
182
183
/* per shader-stage dirty state: */
184
enum fd_dirty_shader_state {
185
FD_DIRTY_SHADER_PROG = BIT(0),
186
FD_DIRTY_SHADER_CONST = BIT(1),
187
FD_DIRTY_SHADER_TEX = BIT(2),
188
FD_DIRTY_SHADER_SSBO = BIT(3),
189
FD_DIRTY_SHADER_IMAGE = BIT(4),
190
#define NUM_DIRTY_SHADER_BITS 5
191
};
192
193
#define MAX_HW_SAMPLE_PROVIDERS 7
194
struct fd_hw_sample_provider;
195
struct fd_hw_sample;
196
197
struct ir3_shader_key;
198
199
struct fd_context {
200
struct pipe_context base;
201
202
struct threaded_context *tc;
203
204
struct list_head node; /* node in screen->context_list */
205
206
/* We currently need to serialize emitting GMEM batches, because of
207
* VSC state access in the context.
208
*
209
* In practice this lock should not be contended, since pipe_context
210
* use should be single threaded. But it is needed to protect the
211
* case, with batch reordering where a ctxB batch triggers flushing
212
* a ctxA batch
213
*/
214
simple_mtx_t gmem_lock;
215
216
struct fd_device *dev;
217
struct fd_screen *screen;
218
struct fd_pipe *pipe;
219
220
struct blitter_context *blitter dt;
221
void *clear_rs_state[2] dt;
222
struct primconvert_context *primconvert dt;
223
224
/* slab for pipe_transfer allocations: */
225
struct slab_child_pool transfer_pool dt;
226
struct slab_child_pool transfer_pool_unsync; /* for threaded_context */
227
228
struct fd_autotune autotune dt;
229
230
/**
231
* query related state:
232
*/
233
/*@{*/
234
/* slabs for fd_hw_sample and fd_hw_sample_period allocations: */
235
struct slab_mempool sample_pool dt;
236
struct slab_mempool sample_period_pool dt;
237
238
/* sample-providers for hw queries: */
239
const struct fd_hw_sample_provider
240
*hw_sample_providers[MAX_HW_SAMPLE_PROVIDERS];
241
242
/* list of active queries: */
243
struct list_head hw_active_queries dt;
244
245
/* sample-providers for accumulating hw queries: */
246
const struct fd_acc_sample_provider
247
*acc_sample_providers[MAX_HW_SAMPLE_PROVIDERS];
248
249
/* list of active accumulating queries: */
250
struct list_head acc_active_queries dt;
251
/*@}*/
252
253
/* Whether we need to recheck the active_queries list next
254
* fd_batch_update_queries().
255
*/
256
bool update_active_queries dt;
257
258
/* Current state of pctx->set_active_query_state() (i.e. "should drawing
259
* be counted against non-perfcounter queries")
260
*/
261
bool active_queries dt;
262
263
/* table with PIPE_PRIM_MAX entries mapping PIPE_PRIM_x to
264
* DI_PT_x value to use for draw initiator. There are some
265
* slight differences between generation:
266
*/
267
const uint8_t *primtypes;
268
uint32_t primtype_mask;
269
270
/* shaders used by clear, and gmem->mem blits: */
271
struct fd_program_stateobj solid_prog; // TODO move to screen?
272
struct fd_program_stateobj solid_layered_prog;
273
274
/* shaders used by mem->gmem blits: */
275
struct fd_program_stateobj
276
blit_prog[MAX_RENDER_TARGETS]; // TODO move to screen?
277
struct fd_program_stateobj blit_z, blit_zs;
278
279
/* Stats/counters:
280
*/
281
struct {
282
uint64_t prims_emitted;
283
uint64_t prims_generated;
284
uint64_t draw_calls;
285
uint64_t batch_total, batch_sysmem, batch_gmem, batch_nondraw,
286
batch_restore;
287
uint64_t staging_uploads, shadow_uploads;
288
uint64_t vs_regs, hs_regs, ds_regs, gs_regs, fs_regs;
289
} stats dt;
290
291
/* Counter for number of users who need sw counters (so we can
292
* skip collecting them when not needed)
293
*/
294
unsigned stats_users;
295
296
/* Current batch.. the rule here is that you can deref ctx->batch
297
* in codepaths from pipe_context entrypoints. But not in code-
298
* paths from fd_batch_flush() (basically, the stuff that gets
299
* called from GMEM code), since in those code-paths the batch
300
* you care about is not necessarily the same as ctx->batch.
301
*/
302
struct fd_batch *batch dt;
303
304
/* NULL if there has been rendering since last flush. Otherwise
305
* keeps a reference to the last fence so we can re-use it rather
306
* than having to flush no-op batch.
307
*/
308
struct pipe_fence_handle *last_fence dt;
309
310
/* Fence fd we are told to wait on via ->fence_server_sync() (or -1
311
* if none). The in-fence is transferred over to the batch on the
312
* next draw/blit/grid.
313
*
314
* The reason for this extra complexity is that apps will typically
315
* do eglWaitSyncKHR()/etc at the beginning of the frame, before the
316
* first draw. But mesa/st doesn't flush down framebuffer state
317
* change until we hit a draw, so at ->fence_server_sync() time, we
318
* don't yet have the correct batch. If we created a batch at that
319
* point, it would be the wrong one, and we'd have to flush it pre-
320
* maturely, causing us to stall early in the frame where we could
321
* be building up cmdstream.
322
*/
323
int in_fence_fd dt;
324
325
/* track last known reset status globally and per-context to
326
* determine if more resets occurred since then. If global reset
327
* count increases, it means some other context crashed. If
328
* per-context reset count increases, it means we crashed the
329
* gpu.
330
*/
331
uint32_t context_reset_count dt;
332
uint32_t global_reset_count dt;
333
334
/* Context sequence #, used for batch-cache key: */
335
uint16_t seqno;
336
337
/* Cost per draw, used in conjunction with samples-passed history to
338
* estimate whether GMEM or bypass is the better option.
339
*/
340
uint8_t draw_cost;
341
342
/* Are we in process of shadowing a resource? Used to detect recursion
343
* in transfer_map, and skip unneeded synchronization.
344
*/
345
bool in_shadow : 1 dt;
346
347
/* For catching recursion problems with blit fallback: */
348
bool in_blit : 1 dt;
349
350
/* points to either scissor or disabled_scissor depending on rast state: */
351
struct pipe_scissor_state *current_scissor dt;
352
353
struct pipe_scissor_state scissor dt;
354
355
/* we don't have a disable/enable bit for scissor, so instead we keep
356
* a disabled-scissor state which matches the entire bound framebuffer
357
* and use that when scissor is not enabled.
358
*/
359
struct pipe_scissor_state disabled_scissor dt;
360
361
/* Per vsc pipe bo's (a2xx-a5xx): */
362
struct fd_bo *vsc_pipe_bo[32] dt;
363
364
/* Maps generic gallium oriented fd_dirty_3d_state bits to generation
365
* specific bitmask of state "groups".
366
*/
367
uint32_t gen_dirty_map[NUM_DIRTY_BITS];
368
uint32_t gen_dirty_shader_map[PIPE_SHADER_TYPES][NUM_DIRTY_SHADER_BITS];
369
370
/* Bitmask of all possible gen_dirty bits: */
371
uint32_t gen_all_dirty;
372
373
/* Generation specific bitmask of dirty state groups: */
374
uint32_t gen_dirty;
375
376
/* which state objects need to be re-emit'd: */
377
enum fd_dirty_3d_state dirty dt;
378
379
/* per shader-stage dirty status: */
380
enum fd_dirty_shader_state dirty_shader[PIPE_SHADER_TYPES] dt;
381
382
void *compute dt;
383
struct pipe_blend_state *blend dt;
384
struct pipe_rasterizer_state *rasterizer dt;
385
struct pipe_depth_stencil_alpha_state *zsa dt;
386
387
struct fd_texture_stateobj tex[PIPE_SHADER_TYPES] dt;
388
389
struct fd_program_stateobj prog dt;
390
uint32_t bound_shader_stages dt;
391
392
struct fd_vertex_state vtx dt;
393
394
struct pipe_blend_color blend_color dt;
395
struct pipe_stencil_ref stencil_ref dt;
396
unsigned sample_mask dt;
397
unsigned min_samples dt;
398
/* local context fb state, for when ctx->batch is null: */
399
struct pipe_framebuffer_state framebuffer dt;
400
struct pipe_poly_stipple stipple dt;
401
struct pipe_viewport_state viewport dt;
402
struct pipe_scissor_state viewport_scissor dt;
403
struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES] dt;
404
struct fd_shaderbuf_stateobj shaderbuf[PIPE_SHADER_TYPES] dt;
405
struct fd_shaderimg_stateobj shaderimg[PIPE_SHADER_TYPES] dt;
406
struct fd_streamout_stateobj streamout dt;
407
struct fd_global_bindings_stateobj global_bindings dt;
408
struct pipe_clip_state ucp dt;
409
410
struct pipe_query *cond_query dt;
411
bool cond_cond dt; /* inverted rendering condition */
412
uint cond_mode dt;
413
414
/* Private memory is a memory space where each fiber gets its own piece of
415
* memory, in addition to registers. It is backed by a buffer which needs
416
* to be large enough to hold the contents of every possible wavefront in
417
* every core of the GPU. Because it allocates space via the internal
418
* wavefront ID which is shared between all currently executing shaders,
419
* the same buffer can be reused by all shaders, as long as all shaders
420
* sharing the same buffer use the exact same configuration. There are two
421
* inputs to the configuration, the amount of per-fiber space and whether
422
* to use the newer per-wave or older per-fiber layout. We only ever
423
* increase the size, and shaders with a smaller size requirement simply
424
* use the larger existing buffer, so that we only need to keep track of
425
* one buffer and its size, but we still need to keep track of per-fiber
426
* and per-wave buffers separately so that we never use the same buffer
427
* for different layouts. pvtmem[0] is for per-fiber, and pvtmem[1] is for
428
* per-wave.
429
*/
430
struct {
431
struct fd_bo *bo;
432
uint32_t per_fiber_size;
433
} pvtmem[2] dt;
434
435
/* maps per-shader-stage state plus variant key to hw
436
* program stateobj:
437
*/
438
struct ir3_cache *shader_cache;
439
440
struct pipe_debug_callback debug;
441
442
struct u_trace_context trace_context dt;
443
444
#ifdef HAVE_PERFETTO
445
struct fd_perfetto_state perfetto;
446
#endif
447
448
/*
449
* Counter to generate submit-ids
450
*/
451
uint32_t submit_count;
452
453
/* Called on rebind_resource() for any per-gen cleanup required: */
454
void (*rebind_resource)(struct fd_context *ctx, struct fd_resource *rsc) dt;
455
456
/* GMEM/tile handling fxns: */
457
void (*emit_tile_init)(struct fd_batch *batch) dt;
458
void (*emit_tile_prep)(struct fd_batch *batch,
459
const struct fd_tile *tile) dt;
460
void (*emit_tile_mem2gmem)(struct fd_batch *batch,
461
const struct fd_tile *tile) dt;
462
void (*emit_tile_renderprep)(struct fd_batch *batch,
463
const struct fd_tile *tile) dt;
464
void (*emit_tile)(struct fd_batch *batch, const struct fd_tile *tile) dt;
465
void (*emit_tile_gmem2mem)(struct fd_batch *batch,
466
const struct fd_tile *tile) dt;
467
void (*emit_tile_fini)(struct fd_batch *batch) dt; /* optional */
468
469
/* optional, for GMEM bypass: */
470
void (*emit_sysmem_prep)(struct fd_batch *batch) dt;
471
void (*emit_sysmem_fini)(struct fd_batch *batch) dt;
472
473
/* draw: */
474
bool (*draw_vbo)(struct fd_context *ctx, const struct pipe_draw_info *info,
475
unsigned drawid_offset,
476
const struct pipe_draw_indirect_info *indirect,
477
const struct pipe_draw_start_count_bias *draw,
478
unsigned index_offset) dt;
479
bool (*clear)(struct fd_context *ctx, unsigned buffers,
480
const union pipe_color_union *color, double depth,
481
unsigned stencil) dt;
482
483
/* compute: */
484
void (*launch_grid)(struct fd_context *ctx,
485
const struct pipe_grid_info *info) dt;
486
487
/* query: */
488
struct fd_query *(*create_query)(struct fd_context *ctx, unsigned query_type,
489
unsigned index);
490
void (*query_prepare)(struct fd_batch *batch, uint32_t num_tiles) dt;
491
void (*query_prepare_tile)(struct fd_batch *batch, uint32_t n,
492
struct fd_ringbuffer *ring) dt;
493
void (*query_update_batch)(struct fd_batch *batch, bool disable_all) dt;
494
495
/* blitter: */
496
bool (*blit)(struct fd_context *ctx, const struct pipe_blit_info *info) dt;
497
void (*clear_ubwc)(struct fd_batch *batch, struct fd_resource *rsc) dt;
498
499
/* uncompress resource, if necessary, to use as the specified format: */
500
void (*validate_format)(struct fd_context *ctx, struct fd_resource *rsc,
501
enum pipe_format format) dt;
502
503
/* handling for barriers: */
504
void (*framebuffer_barrier)(struct fd_context *ctx) dt;
505
506
/* logger: */
507
void (*record_timestamp)(struct fd_ringbuffer *ring, struct fd_bo *bo,
508
unsigned offset);
509
uint64_t (*ts_to_ns)(uint64_t ts);
510
511
/*
512
* Common pre-cooked VBO state (used for a3xx and later):
513
*/
514
515
/* for clear/gmem->mem vertices, and mem->gmem */
516
struct pipe_resource *solid_vbuf;
517
518
/* for mem->gmem tex coords: */
519
struct pipe_resource *blit_texcoord_vbuf;
520
521
/* vertex state for solid_vbuf:
522
* - solid_vbuf / 12 / R32G32B32_FLOAT
523
*/
524
struct fd_vertex_state solid_vbuf_state;
525
526
/* vertex state for blit_prog:
527
* - blit_texcoord_vbuf / 8 / R32G32_FLOAT
528
* - solid_vbuf / 12 / R32G32B32_FLOAT
529
*/
530
struct fd_vertex_state blit_vbuf_state;
531
532
/*
533
* Info about state of previous draw, for state that comes from
534
* pipe_draw_info (ie. not part of a CSO). This allows us to
535
* skip some register emit when the state doesn't change from
536
* draw-to-draw
537
*/
538
struct {
539
bool dirty; /* last draw state unknown */
540
bool primitive_restart;
541
uint32_t index_start;
542
uint32_t instance_start;
543
uint32_t restart_index;
544
uint32_t streamout_mask;
545
546
/* some state changes require a different shader variant. Keep
547
* track of this so we know when we need to re-emit shader state
548
* due to variant change. See ir3_fixup_shader_state()
549
*
550
* (used for a3xx+, NULL otherwise)
551
*/
552
struct ir3_shader_key *key;
553
554
} last dt;
555
};
556
557
static inline struct fd_context *
558
fd_context(struct pipe_context *pctx)
559
{
560
return (struct fd_context *)pctx;
561
}
562
563
static inline struct fd_stream_output_target *
564
fd_stream_output_target(struct pipe_stream_output_target *target)
565
{
566
return (struct fd_stream_output_target *)target;
567
}
568
569
/**
570
* Does the dirty state require resource tracking, ie. in general
571
* does it reference some resource. There are some special cases:
572
*
573
* - FD_DIRTY_CONST can reference a resource, but cb0 is handled
574
* specially as if it is not a user-buffer, we expect it to be
575
* coming from const_uploader, so we can make some assumptions
576
* that future transfer_map will be UNSYNCRONIZED
577
* - FD_DIRTY_ZSA controls how the framebuffer is accessed
578
* - FD_DIRTY_BLEND needs to update GMEM reason
579
*
580
* TODO if we can make assumptions that framebuffer state is bound
581
* first, before blend/zsa/etc state we can move some of the ZSA/
582
* BLEND state handling from draw time to bind time. I think this
583
* is true of mesa/st, perhaps we can just document it to be a
584
* frontend requirement?
585
*/
586
static inline bool
587
fd_context_dirty_resource(enum fd_dirty_3d_state dirty)
588
{
589
return dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_ZSA | FD_DIRTY_BLEND |
590
FD_DIRTY_SSBO | FD_DIRTY_IMAGE | FD_DIRTY_VTXBUF |
591
FD_DIRTY_TEX | FD_DIRTY_STREAMOUT);
592
}
593
594
#ifdef __cplusplus
595
#define or_dirty(d, mask) \
596
do { \
597
decltype(mask) _d = (d); \
598
d = (decltype(mask))(_d | (mask)); \
599
} while (0)
600
#else
601
#define or_dirty(d, mask) \
602
do { \
603
d |= (mask); \
604
} while (0)
605
#endif
606
607
/* Mark specified non-shader-stage related state as dirty: */
608
static inline void
609
fd_context_dirty(struct fd_context *ctx, enum fd_dirty_3d_state dirty) assert_dt
610
{
611
assert(util_is_power_of_two_nonzero(dirty));
612
STATIC_ASSERT(ffs(dirty) <= ARRAY_SIZE(ctx->gen_dirty_map));
613
614
ctx->gen_dirty |= ctx->gen_dirty_map[ffs(dirty) - 1];
615
616
if (fd_context_dirty_resource(dirty))
617
or_dirty(dirty, FD_DIRTY_RESOURCE);
618
619
or_dirty(ctx->dirty, dirty);
620
}
621
622
static inline void
623
fd_context_dirty_shader(struct fd_context *ctx, enum pipe_shader_type shader,
624
enum fd_dirty_shader_state dirty) assert_dt
625
{
626
const enum fd_dirty_3d_state map[] = {
627
FD_DIRTY_PROG, FD_DIRTY_CONST, FD_DIRTY_TEX,
628
FD_DIRTY_SSBO, FD_DIRTY_IMAGE,
629
};
630
631
/* Need to update the table above if these shift: */
632
STATIC_ASSERT(FD_DIRTY_SHADER_PROG == BIT(0));
633
STATIC_ASSERT(FD_DIRTY_SHADER_CONST == BIT(1));
634
STATIC_ASSERT(FD_DIRTY_SHADER_TEX == BIT(2));
635
STATIC_ASSERT(FD_DIRTY_SHADER_SSBO == BIT(3));
636
STATIC_ASSERT(FD_DIRTY_SHADER_IMAGE == BIT(4));
637
638
assert(util_is_power_of_two_nonzero(dirty));
639
assert(ffs(dirty) <= ARRAY_SIZE(map));
640
641
ctx->gen_dirty |= ctx->gen_dirty_shader_map[shader][ffs(dirty) - 1];
642
643
or_dirty(ctx->dirty_shader[shader], dirty);
644
fd_context_dirty(ctx, map[ffs(dirty) - 1]);
645
}
646
647
/* mark all state dirty: */
648
static inline void
649
fd_context_all_dirty(struct fd_context *ctx) assert_dt
650
{
651
ctx->last.dirty = true;
652
ctx->dirty = (enum fd_dirty_3d_state) ~0;
653
654
/* NOTE: don't use ~0 for gen_dirty, because the gen specific
655
* emit code will loop over all the bits:
656
*/
657
ctx->gen_dirty = ctx->gen_all_dirty;
658
659
for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++)
660
ctx->dirty_shader[i] = (enum fd_dirty_shader_state) ~0;
661
}
662
663
static inline void
664
fd_context_all_clean(struct fd_context *ctx) assert_dt
665
{
666
ctx->last.dirty = false;
667
ctx->dirty = (enum fd_dirty_3d_state)0;
668
ctx->gen_dirty = 0;
669
for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) {
670
/* don't mark compute state as clean, since it is not emitted
671
* during normal draw call. The places that call _all_dirty(),
672
* it is safe to mark compute state dirty as well, but the
673
* inverse is not true.
674
*/
675
if (i == PIPE_SHADER_COMPUTE)
676
continue;
677
ctx->dirty_shader[i] = (enum fd_dirty_shader_state)0;
678
}
679
}
680
681
/**
682
* Add mapping between global dirty bit and generation specific dirty
683
* bit.
684
*/
685
static inline void
686
fd_context_add_map(struct fd_context *ctx, enum fd_dirty_3d_state dirty,
687
uint32_t gen_dirty)
688
{
689
u_foreach_bit (b, dirty) {
690
ctx->gen_dirty_map[b] |= gen_dirty;
691
}
692
ctx->gen_all_dirty |= gen_dirty;
693
}
694
695
/**
696
* Add mapping between shader stage specific dirty bit and generation
697
* specific dirty bit
698
*/
699
static inline void
700
fd_context_add_shader_map(struct fd_context *ctx, enum pipe_shader_type shader,
701
enum fd_dirty_shader_state dirty, uint32_t gen_dirty)
702
{
703
u_foreach_bit (b, dirty) {
704
ctx->gen_dirty_shader_map[shader][b] |= gen_dirty;
705
}
706
ctx->gen_all_dirty |= gen_dirty;
707
}
708
709
static inline struct pipe_scissor_state *
710
fd_context_get_scissor(struct fd_context *ctx) assert_dt
711
{
712
return ctx->current_scissor;
713
}
714
715
static inline bool
716
fd_supported_prim(struct fd_context *ctx, unsigned prim)
717
{
718
return (1 << prim) & ctx->primtype_mask;
719
}
720
721
void fd_context_switch_from(struct fd_context *ctx) assert_dt;
722
void fd_context_switch_to(struct fd_context *ctx,
723
struct fd_batch *batch) assert_dt;
724
struct fd_batch *fd_context_batch(struct fd_context *ctx) assert_dt;
725
struct fd_batch *fd_context_batch_locked(struct fd_context *ctx) assert_dt;
726
727
void fd_context_setup_common_vbos(struct fd_context *ctx);
728
void fd_context_cleanup_common_vbos(struct fd_context *ctx);
729
void fd_emit_string(struct fd_ringbuffer *ring, const char *string, int len);
730
void fd_emit_string5(struct fd_ringbuffer *ring, const char *string, int len);
731
732
struct pipe_context *fd_context_init(struct fd_context *ctx,
733
struct pipe_screen *pscreen,
734
const uint8_t *primtypes, void *priv,
735
unsigned flags);
736
struct pipe_context *fd_context_init_tc(struct pipe_context *pctx,
737
unsigned flags);
738
739
void fd_context_destroy(struct pipe_context *pctx) assert_dt;
740
741
#ifdef __cplusplus
742
}
743
#endif
744
745
#endif /* FREEDRENO_CONTEXT_H_ */
746
747