Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/v3d/v3dx_state.c
4570 views
1
/*
2
* Copyright © 2014-2017 Broadcom
3
* Copyright (C) 2012 Rob Clark <[email protected]>
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice (including the next
13
* paragraph) shall be included in all copies or substantial portions of the
14
* Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
* IN THE SOFTWARE.
23
*/
24
25
#include "pipe/p_state.h"
26
#include "util/format/u_format.h"
27
#include "util/u_framebuffer.h"
28
#include "util/u_inlines.h"
29
#include "util/u_math.h"
30
#include "util/u_memory.h"
31
#include "util/half_float.h"
32
#include "util/u_helpers.h"
33
#include "util/u_upload_mgr.h"
34
35
#include "v3d_context.h"
36
#include "broadcom/common/v3d_tiling.h"
37
#include "broadcom/common/v3d_macros.h"
38
#include "broadcom/compiler/v3d_compiler.h"
39
#include "broadcom/cle/v3dx_pack.h"
40
41
static void
42
v3d_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso)
43
{
44
free(hwcso);
45
}
46
47
static void
48
v3d_set_blend_color(struct pipe_context *pctx,
49
const struct pipe_blend_color *blend_color)
50
{
51
struct v3d_context *v3d = v3d_context(pctx);
52
v3d->blend_color.f = *blend_color;
53
for (int i = 0; i < 4; i++) {
54
v3d->blend_color.hf[i] =
55
_mesa_float_to_half(blend_color->color[i]);
56
}
57
v3d->dirty |= V3D_DIRTY_BLEND_COLOR;
58
}
59
60
static void
61
v3d_set_stencil_ref(struct pipe_context *pctx,
62
const struct pipe_stencil_ref stencil_ref)
63
{
64
struct v3d_context *v3d = v3d_context(pctx);
65
v3d->stencil_ref = stencil_ref;
66
v3d->dirty |= V3D_DIRTY_STENCIL_REF;
67
}
68
69
static void
70
v3d_set_clip_state(struct pipe_context *pctx,
71
const struct pipe_clip_state *clip)
72
{
73
struct v3d_context *v3d = v3d_context(pctx);
74
v3d->clip = *clip;
75
v3d->dirty |= V3D_DIRTY_CLIP;
76
}
77
78
static void
79
v3d_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
80
{
81
struct v3d_context *v3d = v3d_context(pctx);
82
v3d->sample_mask = sample_mask & ((1 << V3D_MAX_SAMPLES) - 1);
83
v3d->dirty |= V3D_DIRTY_SAMPLE_STATE;
84
}
85
86
static void *
87
v3d_create_rasterizer_state(struct pipe_context *pctx,
88
const struct pipe_rasterizer_state *cso)
89
{
90
struct v3d_rasterizer_state *so;
91
92
so = CALLOC_STRUCT(v3d_rasterizer_state);
93
if (!so)
94
return NULL;
95
96
so->base = *cso;
97
98
/* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835,
99
* BCM21553).
100
*/
101
so->point_size = MAX2(cso->point_size, .125f);
102
103
STATIC_ASSERT(sizeof(so->depth_offset) >=
104
cl_packet_length(DEPTH_OFFSET));
105
v3dx_pack(&so->depth_offset, DEPTH_OFFSET, depth) {
106
depth.depth_offset_factor = cso->offset_scale;
107
depth.depth_offset_units = cso->offset_units;
108
}
109
110
/* The HW treats polygon offset units based on a Z24 buffer, so we
111
* need to scale up offset_units if we're only Z16.
112
*/
113
v3dx_pack(&so->depth_offset_z16, DEPTH_OFFSET, depth) {
114
depth.depth_offset_factor = cso->offset_scale;
115
depth.depth_offset_units = cso->offset_units * 256.0;
116
}
117
118
return so;
119
}
120
121
/* Blend state is baked into shaders. */
122
static void *
123
v3d_create_blend_state(struct pipe_context *pctx,
124
const struct pipe_blend_state *cso)
125
{
126
struct v3d_blend_state *so;
127
128
so = CALLOC_STRUCT(v3d_blend_state);
129
if (!so)
130
return NULL;
131
132
so->base = *cso;
133
134
if (cso->independent_blend_enable) {
135
for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) {
136
so->blend_enables |= cso->rt[i].blend_enable << i;
137
138
/* V3D 4.x is when we got independent blend enables. */
139
assert(V3D_VERSION >= 40 ||
140
cso->rt[i].blend_enable == cso->rt[0].blend_enable);
141
}
142
} else {
143
if (cso->rt[0].blend_enable)
144
so->blend_enables = (1 << V3D_MAX_DRAW_BUFFERS) - 1;
145
}
146
147
return so;
148
}
149
150
static uint32_t
151
translate_stencil_op(enum pipe_stencil_op op)
152
{
153
switch (op) {
154
case PIPE_STENCIL_OP_KEEP: return V3D_STENCIL_OP_KEEP;
155
case PIPE_STENCIL_OP_ZERO: return V3D_STENCIL_OP_ZERO;
156
case PIPE_STENCIL_OP_REPLACE: return V3D_STENCIL_OP_REPLACE;
157
case PIPE_STENCIL_OP_INCR: return V3D_STENCIL_OP_INCR;
158
case PIPE_STENCIL_OP_DECR: return V3D_STENCIL_OP_DECR;
159
case PIPE_STENCIL_OP_INCR_WRAP: return V3D_STENCIL_OP_INCWRAP;
160
case PIPE_STENCIL_OP_DECR_WRAP: return V3D_STENCIL_OP_DECWRAP;
161
case PIPE_STENCIL_OP_INVERT: return V3D_STENCIL_OP_INVERT;
162
}
163
unreachable("bad stencil op");
164
}
165
166
static void *
167
v3d_create_depth_stencil_alpha_state(struct pipe_context *pctx,
168
const struct pipe_depth_stencil_alpha_state *cso)
169
{
170
struct v3d_depth_stencil_alpha_state *so;
171
172
so = CALLOC_STRUCT(v3d_depth_stencil_alpha_state);
173
if (!so)
174
return NULL;
175
176
so->base = *cso;
177
178
if (cso->depth_enabled) {
179
switch (cso->depth_func) {
180
case PIPE_FUNC_LESS:
181
case PIPE_FUNC_LEQUAL:
182
so->ez_state = V3D_EZ_LT_LE;
183
break;
184
case PIPE_FUNC_GREATER:
185
case PIPE_FUNC_GEQUAL:
186
so->ez_state = V3D_EZ_GT_GE;
187
break;
188
case PIPE_FUNC_NEVER:
189
case PIPE_FUNC_EQUAL:
190
so->ez_state = V3D_EZ_UNDECIDED;
191
break;
192
default:
193
so->ez_state = V3D_EZ_DISABLED;
194
break;
195
}
196
197
/* If stencil is enabled and it's not a no-op, then it would
198
* break EZ updates.
199
*/
200
if (cso->stencil[0].enabled &&
201
(cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
202
cso->stencil[0].func != PIPE_FUNC_ALWAYS ||
203
(cso->stencil[1].enabled &&
204
(cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP &&
205
cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) {
206
so->ez_state = V3D_EZ_DISABLED;
207
}
208
}
209
210
const struct pipe_stencil_state *front = &cso->stencil[0];
211
const struct pipe_stencil_state *back = &cso->stencil[1];
212
213
if (front->enabled) {
214
STATIC_ASSERT(sizeof(so->stencil_front) >=
215
cl_packet_length(STENCIL_CFG));
216
v3dx_pack(&so->stencil_front, STENCIL_CFG, config) {
217
config.front_config = true;
218
/* If !back->enabled, then the front values should be
219
* used for both front and back-facing primitives.
220
*/
221
config.back_config = !back->enabled;
222
223
config.stencil_write_mask = front->writemask;
224
config.stencil_test_mask = front->valuemask;
225
226
config.stencil_test_function = front->func;
227
config.stencil_pass_op =
228
translate_stencil_op(front->zpass_op);
229
config.depth_test_fail_op =
230
translate_stencil_op(front->zfail_op);
231
config.stencil_test_fail_op =
232
translate_stencil_op(front->fail_op);
233
}
234
}
235
if (back->enabled) {
236
STATIC_ASSERT(sizeof(so->stencil_back) >=
237
cl_packet_length(STENCIL_CFG));
238
v3dx_pack(&so->stencil_back, STENCIL_CFG, config) {
239
config.front_config = false;
240
config.back_config = true;
241
242
config.stencil_write_mask = back->writemask;
243
config.stencil_test_mask = back->valuemask;
244
245
config.stencil_test_function = back->func;
246
config.stencil_pass_op =
247
translate_stencil_op(back->zpass_op);
248
config.depth_test_fail_op =
249
translate_stencil_op(back->zfail_op);
250
config.stencil_test_fail_op =
251
translate_stencil_op(back->fail_op);
252
}
253
}
254
255
return so;
256
}
257
258
static void
259
v3d_set_polygon_stipple(struct pipe_context *pctx,
260
const struct pipe_poly_stipple *stipple)
261
{
262
struct v3d_context *v3d = v3d_context(pctx);
263
v3d->stipple = *stipple;
264
v3d->dirty |= V3D_DIRTY_STIPPLE;
265
}
266
267
static void
268
v3d_set_scissor_states(struct pipe_context *pctx,
269
unsigned start_slot,
270
unsigned num_scissors,
271
const struct pipe_scissor_state *scissor)
272
{
273
struct v3d_context *v3d = v3d_context(pctx);
274
275
v3d->scissor = *scissor;
276
v3d->dirty |= V3D_DIRTY_SCISSOR;
277
}
278
279
static void
280
v3d_set_viewport_states(struct pipe_context *pctx,
281
unsigned start_slot,
282
unsigned num_viewports,
283
const struct pipe_viewport_state *viewport)
284
{
285
struct v3d_context *v3d = v3d_context(pctx);
286
v3d->viewport = *viewport;
287
v3d->dirty |= V3D_DIRTY_VIEWPORT;
288
}
289
290
static void
291
v3d_set_vertex_buffers(struct pipe_context *pctx,
292
unsigned start_slot, unsigned count,
293
unsigned unbind_num_trailing_slots,
294
bool take_ownership,
295
const struct pipe_vertex_buffer *vb)
296
{
297
struct v3d_context *v3d = v3d_context(pctx);
298
struct v3d_vertexbuf_stateobj *so = &v3d->vertexbuf;
299
300
util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb,
301
start_slot, count,
302
unbind_num_trailing_slots,
303
take_ownership);
304
so->count = util_last_bit(so->enabled_mask);
305
306
v3d->dirty |= V3D_DIRTY_VTXBUF;
307
}
308
309
static void
310
v3d_blend_state_bind(struct pipe_context *pctx, void *hwcso)
311
{
312
struct v3d_context *v3d = v3d_context(pctx);
313
v3d->blend = hwcso;
314
v3d->dirty |= V3D_DIRTY_BLEND;
315
}
316
317
static void
318
v3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
319
{
320
struct v3d_context *v3d = v3d_context(pctx);
321
v3d->rasterizer = hwcso;
322
v3d->dirty |= V3D_DIRTY_RASTERIZER;
323
}
324
325
static void
326
v3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
327
{
328
struct v3d_context *v3d = v3d_context(pctx);
329
v3d->zsa = hwcso;
330
v3d->dirty |= V3D_DIRTY_ZSA;
331
}
332
333
static void *
334
v3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
335
const struct pipe_vertex_element *elements)
336
{
337
struct v3d_context *v3d = v3d_context(pctx);
338
struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj);
339
340
if (!so)
341
return NULL;
342
343
memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
344
so->num_elements = num_elements;
345
346
for (int i = 0; i < so->num_elements; i++) {
347
const struct pipe_vertex_element *elem = &elements[i];
348
const struct util_format_description *desc =
349
util_format_description(elem->src_format);
350
uint32_t r_size = desc->channel[0].size;
351
352
const uint32_t size =
353
cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);
354
355
v3dx_pack(&so->attrs[i * size],
356
GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) {
357
/* vec_size == 0 means 4 */
358
attr.vec_size = desc->nr_channels & 3;
359
attr.signed_int_type = (desc->channel[0].type ==
360
UTIL_FORMAT_TYPE_SIGNED);
361
362
attr.normalized_int_type = desc->channel[0].normalized;
363
attr.read_as_int_uint = desc->channel[0].pure_integer;
364
attr.instance_divisor = MIN2(elem->instance_divisor,
365
0xffff);
366
367
switch (desc->channel[0].type) {
368
case UTIL_FORMAT_TYPE_FLOAT:
369
if (r_size == 32) {
370
attr.type = ATTRIBUTE_FLOAT;
371
} else {
372
assert(r_size == 16);
373
attr.type = ATTRIBUTE_HALF_FLOAT;
374
}
375
break;
376
377
case UTIL_FORMAT_TYPE_SIGNED:
378
case UTIL_FORMAT_TYPE_UNSIGNED:
379
switch (r_size) {
380
case 32:
381
attr.type = ATTRIBUTE_INT;
382
break;
383
case 16:
384
attr.type = ATTRIBUTE_SHORT;
385
break;
386
case 10:
387
attr.type = ATTRIBUTE_INT2_10_10_10;
388
break;
389
case 8:
390
attr.type = ATTRIBUTE_BYTE;
391
break;
392
default:
393
fprintf(stderr,
394
"format %s unsupported\n",
395
desc->name);
396
attr.type = ATTRIBUTE_BYTE;
397
abort();
398
}
399
break;
400
401
default:
402
fprintf(stderr,
403
"format %s unsupported\n",
404
desc->name);
405
abort();
406
}
407
}
408
}
409
410
/* Set up the default attribute values in case any of the vertex
411
* elements use them.
412
*/
413
uint32_t *attrs;
414
u_upload_alloc(v3d->state_uploader, 0,
415
V3D_MAX_VS_INPUTS * sizeof(float), 16,
416
&so->defaults_offset, &so->defaults, (void **)&attrs);
417
418
for (int i = 0; i < V3D_MAX_VS_INPUTS / 4; i++) {
419
attrs[i * 4 + 0] = 0;
420
attrs[i * 4 + 1] = 0;
421
attrs[i * 4 + 2] = 0;
422
if (i < so->num_elements &&
423
util_format_is_pure_integer(so->pipe[i].src_format)) {
424
attrs[i * 4 + 3] = 1;
425
} else {
426
attrs[i * 4 + 3] = fui(1.0);
427
}
428
}
429
430
u_upload_unmap(v3d->state_uploader);
431
return so;
432
}
433
434
static void
435
v3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso)
436
{
437
struct v3d_vertex_stateobj *so = hwcso;
438
439
pipe_resource_reference(&so->defaults, NULL);
440
free(so);
441
}
442
443
static void
444
v3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
445
{
446
struct v3d_context *v3d = v3d_context(pctx);
447
v3d->vtx = hwcso;
448
v3d->dirty |= V3D_DIRTY_VTXSTATE;
449
}
450
451
static void
452
v3d_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
453
bool take_ownership,
454
const struct pipe_constant_buffer *cb)
455
{
456
struct v3d_context *v3d = v3d_context(pctx);
457
struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader];
458
459
util_copy_constant_buffer(&so->cb[index], cb, take_ownership);
460
461
/* Note that the gallium frontend can unbind constant buffers by
462
* passing NULL here.
463
*/
464
if (unlikely(!cb)) {
465
so->enabled_mask &= ~(1 << index);
466
so->dirty_mask &= ~(1 << index);
467
return;
468
}
469
470
so->enabled_mask |= 1 << index;
471
so->dirty_mask |= 1 << index;
472
v3d->dirty |= V3D_DIRTY_CONSTBUF;
473
}
474
475
static void
476
v3d_set_framebuffer_state(struct pipe_context *pctx,
477
const struct pipe_framebuffer_state *framebuffer)
478
{
479
struct v3d_context *v3d = v3d_context(pctx);
480
struct pipe_framebuffer_state *cso = &v3d->framebuffer;
481
482
v3d->job = NULL;
483
484
util_copy_framebuffer_state(cso, framebuffer);
485
486
v3d->swap_color_rb = 0;
487
v3d->blend_dst_alpha_one = 0;
488
for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) {
489
struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i];
490
if (!cbuf)
491
continue;
492
struct v3d_surface *v3d_cbuf = v3d_surface(cbuf);
493
494
const struct util_format_description *desc =
495
util_format_description(cbuf->format);
496
497
/* For BGRA8 formats (DRI window system default format), we
498
* need to swap R and B, since the HW's format is RGBA8. On
499
* V3D 4.1+, the RCL can swap R and B on load/store.
500
*/
501
if (v3d->screen->devinfo.ver < 41 && v3d_cbuf->swap_rb)
502
v3d->swap_color_rb |= 1 << i;
503
504
if (desc->swizzle[3] == PIPE_SWIZZLE_1)
505
v3d->blend_dst_alpha_one |= 1 << i;
506
}
507
508
v3d->dirty |= V3D_DIRTY_FRAMEBUFFER;
509
}
510
511
static enum V3DX(Wrap_Mode)
512
translate_wrap(uint32_t pipe_wrap)
513
{
514
switch (pipe_wrap) {
515
case PIPE_TEX_WRAP_REPEAT:
516
return V3D_WRAP_MODE_REPEAT;
517
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
518
return V3D_WRAP_MODE_CLAMP;
519
case PIPE_TEX_WRAP_MIRROR_REPEAT:
520
return V3D_WRAP_MODE_MIRROR;
521
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
522
return V3D_WRAP_MODE_BORDER;
523
default:
524
unreachable("Unknown wrap mode");
525
}
526
}
527
528
#if V3D_VERSION >= 40
529
static void
530
v3d_upload_sampler_state_variant(void *map,
531
const struct pipe_sampler_state *cso,
532
enum v3d_sampler_state_variant variant)
533
{
534
v3dx_pack(map, SAMPLER_STATE, sampler) {
535
sampler.wrap_i_border = false;
536
537
sampler.wrap_s = translate_wrap(cso->wrap_s);
538
sampler.wrap_t = translate_wrap(cso->wrap_t);
539
sampler.wrap_r = translate_wrap(cso->wrap_r);
540
541
sampler.fixed_bias = cso->lod_bias;
542
sampler.depth_compare_function = cso->compare_func;
543
544
sampler.min_filter_nearest =
545
cso->min_img_filter == PIPE_TEX_FILTER_NEAREST;
546
sampler.mag_filter_nearest =
547
cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST;
548
sampler.mip_filter_nearest =
549
cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR;
550
551
sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod),
552
15);
553
sampler.max_level_of_detail = MIN2(MAX2(cso->max_lod,
554
cso->min_lod), 15);
555
556
/* If we're not doing inter-miplevel filtering, we need to
557
* clamp the LOD so that we only sample from baselevel.
558
* However, we need to still allow the calculated LOD to be
559
* fractionally over the baselevel, so that the HW can decide
560
* between the min and mag filters.
561
*/
562
if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
563
sampler.min_level_of_detail =
564
MIN2(sampler.min_level_of_detail, 1.0 / 256.0);
565
sampler.max_level_of_detail =
566
MIN2(sampler.max_level_of_detail, 1.0 / 256.0);
567
}
568
569
if (cso->max_anisotropy) {
570
sampler.anisotropy_enable = true;
571
572
if (cso->max_anisotropy > 8)
573
sampler.maximum_anisotropy = 3;
574
else if (cso->max_anisotropy > 4)
575
sampler.maximum_anisotropy = 2;
576
else if (cso->max_anisotropy > 2)
577
sampler.maximum_anisotropy = 1;
578
}
579
580
if (variant == V3D_SAMPLER_STATE_BORDER_0) {
581
sampler.border_color_mode = V3D_BORDER_COLOR_0000;
582
} else {
583
sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS;
584
585
union pipe_color_union border;
586
587
/* First, reswizzle the border color for any
588
* mismatching we're doing between the texture's
589
* channel order in hardware (R) versus what it is at
590
* the GL level (ALPHA)
591
*/
592
switch (variant) {
593
case V3D_SAMPLER_STATE_F16_BGRA:
594
case V3D_SAMPLER_STATE_F16_BGRA_UNORM:
595
case V3D_SAMPLER_STATE_F16_BGRA_SNORM:
596
border.i[0] = cso->border_color.i[2];
597
border.i[1] = cso->border_color.i[1];
598
border.i[2] = cso->border_color.i[0];
599
border.i[3] = cso->border_color.i[3];
600
break;
601
602
case V3D_SAMPLER_STATE_F16_A:
603
case V3D_SAMPLER_STATE_F16_A_UNORM:
604
case V3D_SAMPLER_STATE_F16_A_SNORM:
605
case V3D_SAMPLER_STATE_32_A:
606
case V3D_SAMPLER_STATE_32_A_UNORM:
607
case V3D_SAMPLER_STATE_32_A_SNORM:
608
border.i[0] = cso->border_color.i[3];
609
border.i[1] = 0;
610
border.i[2] = 0;
611
border.i[3] = 0;
612
break;
613
614
case V3D_SAMPLER_STATE_F16_LA:
615
case V3D_SAMPLER_STATE_F16_LA_UNORM:
616
case V3D_SAMPLER_STATE_F16_LA_SNORM:
617
border.i[0] = cso->border_color.i[0];
618
border.i[1] = cso->border_color.i[3];
619
border.i[2] = 0;
620
border.i[3] = 0;
621
break;
622
623
default:
624
border = cso->border_color;
625
}
626
627
/* Perform any clamping. */
628
switch (variant) {
629
case V3D_SAMPLER_STATE_F16_UNORM:
630
case V3D_SAMPLER_STATE_F16_BGRA_UNORM:
631
case V3D_SAMPLER_STATE_F16_A_UNORM:
632
case V3D_SAMPLER_STATE_F16_LA_UNORM:
633
case V3D_SAMPLER_STATE_32_UNORM:
634
case V3D_SAMPLER_STATE_32_A_UNORM:
635
for (int i = 0; i < 4; i++)
636
border.f[i] = CLAMP(border.f[i], 0, 1);
637
break;
638
639
case V3D_SAMPLER_STATE_F16_SNORM:
640
case V3D_SAMPLER_STATE_F16_BGRA_SNORM:
641
case V3D_SAMPLER_STATE_F16_A_SNORM:
642
case V3D_SAMPLER_STATE_F16_LA_SNORM:
643
case V3D_SAMPLER_STATE_32_SNORM:
644
case V3D_SAMPLER_STATE_32_A_SNORM:
645
for (int i = 0; i < 4; i++)
646
border.f[i] = CLAMP(border.f[i], -1, 1);
647
break;
648
649
case V3D_SAMPLER_STATE_1010102U:
650
border.ui[0] = CLAMP(border.ui[0],
651
0, (1 << 10) - 1);
652
border.ui[1] = CLAMP(border.ui[1],
653
0, (1 << 10) - 1);
654
border.ui[2] = CLAMP(border.ui[2],
655
0, (1 << 10) - 1);
656
border.ui[3] = CLAMP(border.ui[3],
657
0, 3);
658
break;
659
660
case V3D_SAMPLER_STATE_16U:
661
for (int i = 0; i < 4; i++)
662
border.ui[i] = CLAMP(border.ui[i],
663
0, 0xffff);
664
break;
665
666
case V3D_SAMPLER_STATE_16I:
667
for (int i = 0; i < 4; i++)
668
border.i[i] = CLAMP(border.i[i],
669
-32768, 32767);
670
break;
671
672
case V3D_SAMPLER_STATE_8U:
673
for (int i = 0; i < 4; i++)
674
border.ui[i] = CLAMP(border.ui[i],
675
0, 0xff);
676
break;
677
678
case V3D_SAMPLER_STATE_8I:
679
for (int i = 0; i < 4; i++)
680
border.i[i] = CLAMP(border.i[i],
681
-128, 127);
682
break;
683
684
default:
685
break;
686
}
687
688
if (variant >= V3D_SAMPLER_STATE_32) {
689
sampler.border_color_word_0 = border.ui[0];
690
sampler.border_color_word_1 = border.ui[1];
691
sampler.border_color_word_2 = border.ui[2];
692
sampler.border_color_word_3 = border.ui[3];
693
} else {
694
sampler.border_color_word_0 =
695
_mesa_float_to_half(border.f[0]);
696
sampler.border_color_word_1 =
697
_mesa_float_to_half(border.f[1]);
698
sampler.border_color_word_2 =
699
_mesa_float_to_half(border.f[2]);
700
sampler.border_color_word_3 =
701
_mesa_float_to_half(border.f[3]);
702
}
703
}
704
}
705
}
706
#endif
707
708
static void *
709
v3d_create_sampler_state(struct pipe_context *pctx,
710
const struct pipe_sampler_state *cso)
711
{
712
UNUSED struct v3d_context *v3d = v3d_context(pctx);
713
struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state);
714
715
if (!so)
716
return NULL;
717
718
memcpy(so, cso, sizeof(*cso));
719
720
enum V3DX(Wrap_Mode) wrap_s = translate_wrap(cso->wrap_s);
721
enum V3DX(Wrap_Mode) wrap_t = translate_wrap(cso->wrap_t);
722
enum V3DX(Wrap_Mode) wrap_r = translate_wrap(cso->wrap_r);
723
724
bool uses_border_color = (wrap_s == V3D_WRAP_MODE_BORDER ||
725
wrap_t == V3D_WRAP_MODE_BORDER ||
726
wrap_r == V3D_WRAP_MODE_BORDER);
727
so->border_color_variants = (uses_border_color &&
728
(cso->border_color.ui[0] != 0 ||
729
cso->border_color.ui[1] != 0 ||
730
cso->border_color.ui[2] != 0 ||
731
cso->border_color.ui[3] != 0));
732
733
#if V3D_VERSION >= 40
734
void *map;
735
int sampler_align = so->border_color_variants ? 32 : 8;
736
int sampler_size = align(cl_packet_length(SAMPLER_STATE), sampler_align);
737
int num_variants = (so->border_color_variants ? ARRAY_SIZE(so->sampler_state_offset) : 1);
738
u_upload_alloc(v3d->state_uploader, 0,
739
sampler_size * num_variants,
740
sampler_align,
741
&so->sampler_state_offset[0],
742
&so->sampler_state,
743
&map);
744
745
for (int i = 0; i < num_variants; i++) {
746
so->sampler_state_offset[i] =
747
so->sampler_state_offset[0] + i * sampler_size;
748
v3d_upload_sampler_state_variant(map + i * sampler_size,
749
cso, i);
750
}
751
752
#else /* V3D_VERSION < 40 */
753
v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) {
754
p0.s_wrap_mode = wrap_s;
755
p0.t_wrap_mode = wrap_t;
756
p0.r_wrap_mode = wrap_r;
757
}
758
759
v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) {
760
tex.depth_compare_function = cso->compare_func;
761
tex.fixed_bias = cso->lod_bias;
762
}
763
#endif /* V3D_VERSION < 40 */
764
return so;
765
}
766
767
static void
768
v3d_sampler_states_bind(struct pipe_context *pctx,
769
enum pipe_shader_type shader, unsigned start,
770
unsigned nr, void **hwcso)
771
{
772
struct v3d_context *v3d = v3d_context(pctx);
773
struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader];
774
775
assert(start == 0);
776
unsigned i;
777
unsigned new_nr = 0;
778
779
for (i = 0; i < nr; i++) {
780
if (hwcso[i])
781
new_nr = i + 1;
782
stage_tex->samplers[i] = hwcso[i];
783
}
784
785
for (; i < stage_tex->num_samplers; i++) {
786
stage_tex->samplers[i] = NULL;
787
}
788
789
stage_tex->num_samplers = new_nr;
790
791
v3d_flag_dirty_sampler_state(v3d, shader);
792
}
793
794
static void
795
v3d_sampler_state_delete(struct pipe_context *pctx,
796
void *hwcso)
797
{
798
struct pipe_sampler_state *psampler = hwcso;
799
struct v3d_sampler_state *sampler = v3d_sampler_state(psampler);
800
801
pipe_resource_reference(&sampler->sampler_state, NULL);
802
free(psampler);
803
}
804
805
#if V3D_VERSION >= 40
806
static uint32_t
807
translate_swizzle(unsigned char pipe_swizzle)
808
{
809
switch (pipe_swizzle) {
810
case PIPE_SWIZZLE_0:
811
return 0;
812
case PIPE_SWIZZLE_1:
813
return 1;
814
case PIPE_SWIZZLE_X:
815
case PIPE_SWIZZLE_Y:
816
case PIPE_SWIZZLE_Z:
817
case PIPE_SWIZZLE_W:
818
return 2 + pipe_swizzle;
819
default:
820
unreachable("unknown swizzle");
821
}
822
}
823
#endif
824
825
static void
826
v3d_setup_texture_shader_state(struct V3DX(TEXTURE_SHADER_STATE) *tex,
827
struct pipe_resource *prsc,
828
int base_level, int last_level,
829
int first_layer, int last_layer)
830
{
831
struct v3d_resource *rsc = v3d_resource(prsc);
832
int msaa_scale = prsc->nr_samples > 1 ? 2 : 1;
833
834
tex->image_width = prsc->width0 * msaa_scale;
835
tex->image_height = prsc->height0 * msaa_scale;
836
837
#if V3D_VERSION >= 40
838
/* On 4.x, the height of a 1D texture is redefined to be the
839
* upper 14 bits of the width (which is only usable with txf).
840
*/
841
if (prsc->target == PIPE_TEXTURE_1D ||
842
prsc->target == PIPE_TEXTURE_1D_ARRAY) {
843
tex->image_height = tex->image_width >> 14;
844
}
845
846
tex->image_width &= (1 << 14) - 1;
847
tex->image_height &= (1 << 14) - 1;
848
#endif
849
850
if (prsc->target == PIPE_TEXTURE_3D) {
851
tex->image_depth = prsc->depth0;
852
} else {
853
tex->image_depth = (last_layer - first_layer) + 1;
854
}
855
856
tex->base_level = base_level;
857
#if V3D_VERSION >= 40
858
tex->max_level = last_level;
859
/* Note that we don't have a job to reference the texture's sBO
860
* at state create time, so any time this sampler view is used
861
* we need to add the texture to the job.
862
*/
863
tex->texture_base_pointer =
864
cl_address(NULL,
865
rsc->bo->offset +
866
v3d_layer_offset(prsc, 0, first_layer));
867
#endif
868
tex->array_stride_64_byte_aligned = rsc->cube_map_stride / 64;
869
870
/* Since other platform devices may produce UIF images even
871
* when they're not big enough for V3D to assume they're UIF,
872
* we force images with level 0 as UIF to be always treated
873
* that way.
874
*/
875
tex->level_0_is_strictly_uif =
876
(rsc->slices[0].tiling == V3D_TILING_UIF_XOR ||
877
rsc->slices[0].tiling == V3D_TILING_UIF_NO_XOR);
878
tex->level_0_xor_enable = (rsc->slices[0].tiling == V3D_TILING_UIF_XOR);
879
880
if (tex->level_0_is_strictly_uif)
881
tex->level_0_ub_pad = rsc->slices[0].ub_pad;
882
883
#if V3D_VERSION >= 40
884
if (tex->uif_xor_disable ||
885
tex->level_0_is_strictly_uif) {
886
tex->extended = true;
887
}
888
#endif /* V3D_VERSION >= 40 */
889
}
890
891
void
892
v3dX(create_texture_shader_state_bo)(struct v3d_context *v3d,
893
struct v3d_sampler_view *so)
894
{
895
struct pipe_resource *prsc = so->texture;
896
const struct pipe_sampler_view *cso = &so->base;
897
struct v3d_screen *screen = v3d->screen;
898
899
void *map;
900
901
#if V3D_VERSION >= 40
902
v3d_bo_unreference(&so->bo);
903
so->bo = v3d_bo_alloc(v3d->screen,
904
cl_packet_length(TEXTURE_SHADER_STATE), "sampler");
905
map = v3d_bo_map(so->bo);
906
#else /* V3D_VERSION < 40 */
907
STATIC_ASSERT(sizeof(so->texture_shader_state) >=
908
cl_packet_length(TEXTURE_SHADER_STATE));
909
map = &so->texture_shader_state;
910
#endif
911
912
v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
913
v3d_setup_texture_shader_state(&tex, prsc,
914
cso->u.tex.first_level,
915
cso->u.tex.last_level,
916
cso->u.tex.first_layer,
917
cso->u.tex.last_layer);
918
919
tex.srgb = util_format_is_srgb(cso->format);
920
921
#if V3D_VERSION >= 40
922
tex.swizzle_r = translate_swizzle(so->swizzle[0]);
923
tex.swizzle_g = translate_swizzle(so->swizzle[1]);
924
tex.swizzle_b = translate_swizzle(so->swizzle[2]);
925
tex.swizzle_a = translate_swizzle(so->swizzle[3]);
926
#endif
927
928
if (prsc->nr_samples > 1 && V3D_VERSION < 40) {
929
/* Using texture views to reinterpret formats on our
930
* MSAA textures won't work, because we don't lay out
931
* the bits in memory as it's expected -- for example,
932
* RGBA8 and RGB10_A2 are compatible in the
933
* ARB_texture_view spec, but in HW we lay them out as
934
* 32bpp RGBA8 and 64bpp RGBA16F. Just assert for now
935
* to catch failures.
936
*
937
* We explicitly allow remapping S8Z24 to RGBA8888 for
938
* v3d_blit.c's stencil blits.
939
*/
940
assert((util_format_linear(cso->format) ==
941
util_format_linear(prsc->format)) ||
942
(prsc->format == PIPE_FORMAT_S8_UINT_Z24_UNORM &&
943
cso->format == PIPE_FORMAT_R8G8B8A8_UNORM));
944
uint32_t output_image_format =
945
v3d_get_rt_format(&screen->devinfo, cso->format);
946
uint32_t internal_type;
947
uint32_t internal_bpp;
948
v3d_get_internal_type_bpp_for_output_format(&screen->devinfo,
949
output_image_format,
950
&internal_type,
951
&internal_bpp);
952
953
switch (internal_type) {
954
case V3D_INTERNAL_TYPE_8:
955
tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8;
956
break;
957
case V3D_INTERNAL_TYPE_16F:
958
tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F;
959
break;
960
default:
961
unreachable("Bad MSAA texture type");
962
}
963
964
/* sRGB was stored in the tile buffer as linear and
965
* would have been encoded to sRGB on resolved tile
966
* buffer store. Note that this means we would need
967
* shader code if we wanted to read an MSAA sRGB
968
* texture without sRGB decode.
969
*/
970
tex.srgb = false;
971
} else {
972
tex.texture_type = v3d_get_tex_format(&screen->devinfo,
973
cso->format);
974
}
975
};
976
}
977
978
static struct pipe_sampler_view *
979
v3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
980
const struct pipe_sampler_view *cso)
981
{
982
struct v3d_context *v3d = v3d_context(pctx);
983
struct v3d_screen *screen = v3d->screen;
984
struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view);
985
struct v3d_resource *rsc = v3d_resource(prsc);
986
987
if (!so)
988
return NULL;
989
990
so->base = *cso;
991
992
pipe_reference(NULL, &prsc->reference);
993
994
/* Compute the sampler view's swizzle up front. This will be plugged
995
* into either the sampler (for 16-bit returns) or the shader's
996
* texture key (for 32)
997
*/
998
uint8_t view_swizzle[4] = {
999
cso->swizzle_r,
1000
cso->swizzle_g,
1001
cso->swizzle_b,
1002
cso->swizzle_a
1003
};
1004
const uint8_t *fmt_swizzle =
1005
v3d_get_format_swizzle(&screen->devinfo, so->base.format);
1006
util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle);
1007
1008
so->base.texture = prsc;
1009
so->base.reference.count = 1;
1010
so->base.context = pctx;
1011
1012
if (rsc->separate_stencil &&
1013
cso->format == PIPE_FORMAT_X32_S8X24_UINT) {
1014
rsc = rsc->separate_stencil;
1015
prsc = &rsc->base;
1016
}
1017
1018
/* If we're sampling depth from depth/stencil, demote the format to
1019
* just depth. u_format will end up giving the answers for the
1020
* stencil channel, otherwise.
1021
*/
1022
enum pipe_format sample_format = cso->format;
1023
if (sample_format == PIPE_FORMAT_S8_UINT_Z24_UNORM)
1024
sample_format = PIPE_FORMAT_X8Z24_UNORM;
1025
1026
#if V3D_VERSION >= 40
1027
const struct util_format_description *desc =
1028
util_format_description(sample_format);
1029
1030
if (util_format_is_pure_integer(sample_format) &&
1031
!util_format_has_depth(desc)) {
1032
int chan = util_format_get_first_non_void_channel(sample_format);
1033
if (util_format_is_pure_uint(sample_format)) {
1034
switch (desc->channel[chan].size) {
1035
case 32:
1036
so->sampler_variant = V3D_SAMPLER_STATE_32;
1037
break;
1038
case 16:
1039
so->sampler_variant = V3D_SAMPLER_STATE_16U;
1040
break;
1041
case 10:
1042
so->sampler_variant = V3D_SAMPLER_STATE_1010102U;
1043
break;
1044
case 8:
1045
so->sampler_variant = V3D_SAMPLER_STATE_8U;
1046
break;
1047
}
1048
} else {
1049
switch (desc->channel[chan].size) {
1050
case 32:
1051
so->sampler_variant = V3D_SAMPLER_STATE_32;
1052
break;
1053
case 16:
1054
so->sampler_variant = V3D_SAMPLER_STATE_16I;
1055
break;
1056
case 8:
1057
so->sampler_variant = V3D_SAMPLER_STATE_8I;
1058
break;
1059
}
1060
}
1061
} else {
1062
if (v3d_get_tex_return_size(&screen->devinfo, sample_format,
1063
PIPE_TEX_COMPARE_NONE) == 32) {
1064
if (util_format_is_alpha(sample_format))
1065
so->sampler_variant = V3D_SAMPLER_STATE_32_A;
1066
else
1067
so->sampler_variant = V3D_SAMPLER_STATE_32;
1068
} else {
1069
if (util_format_is_luminance_alpha(sample_format))
1070
so->sampler_variant = V3D_SAMPLER_STATE_F16_LA;
1071
else if (util_format_is_alpha(sample_format))
1072
so->sampler_variant = V3D_SAMPLER_STATE_F16_A;
1073
else if (fmt_swizzle[0] == PIPE_SWIZZLE_Z)
1074
so->sampler_variant = V3D_SAMPLER_STATE_F16_BGRA;
1075
else
1076
so->sampler_variant = V3D_SAMPLER_STATE_F16;
1077
1078
}
1079
1080
if (util_format_is_unorm(sample_format)) {
1081
so->sampler_variant += (V3D_SAMPLER_STATE_F16_UNORM -
1082
V3D_SAMPLER_STATE_F16);
1083
} else if (util_format_is_snorm(sample_format)){
1084
so->sampler_variant += (V3D_SAMPLER_STATE_F16_SNORM -
1085
V3D_SAMPLER_STATE_F16);
1086
}
1087
}
1088
#endif
1089
1090
/* V3D still doesn't support sampling from raster textures, so we will
1091
* have to copy to a temporary tiled texture.
1092
*/
1093
if (!rsc->tiled && !(prsc->target == PIPE_TEXTURE_1D ||
1094
prsc->target == PIPE_TEXTURE_1D_ARRAY)) {
1095
struct v3d_resource *shadow_parent = rsc;
1096
struct pipe_resource tmpl = {
1097
.target = prsc->target,
1098
.format = prsc->format,
1099
.width0 = u_minify(prsc->width0,
1100
cso->u.tex.first_level),
1101
.height0 = u_minify(prsc->height0,
1102
cso->u.tex.first_level),
1103
.depth0 = 1,
1104
.array_size = 1,
1105
.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
1106
.last_level = cso->u.tex.last_level - cso->u.tex.first_level,
1107
.nr_samples = prsc->nr_samples,
1108
};
1109
1110
/* Create the shadow texture. The rest of the sampler view
1111
* setup will use the shadow.
1112
*/
1113
prsc = v3d_resource_create(pctx->screen, &tmpl);
1114
if (!prsc) {
1115
free(so);
1116
return NULL;
1117
}
1118
rsc = v3d_resource(prsc);
1119
1120
/* Flag it as needing update of the contents from the parent. */
1121
rsc->writes = shadow_parent->writes - 1;
1122
assert(rsc->tiled);
1123
1124
so->texture = prsc;
1125
} else {
1126
pipe_resource_reference(&so->texture, prsc);
1127
}
1128
1129
v3d_create_texture_shader_state_bo(v3d, so);
1130
1131
return &so->base;
1132
}
1133
1134
static void
1135
v3d_sampler_view_destroy(struct pipe_context *pctx,
1136
struct pipe_sampler_view *psview)
1137
{
1138
struct v3d_sampler_view *sview = v3d_sampler_view(psview);
1139
1140
v3d_bo_unreference(&sview->bo);
1141
pipe_resource_reference(&psview->texture, NULL);
1142
pipe_resource_reference(&sview->texture, NULL);
1143
free(psview);
1144
}
1145
1146
static void
1147
v3d_set_sampler_views(struct pipe_context *pctx,
1148
enum pipe_shader_type shader,
1149
unsigned start, unsigned nr,
1150
unsigned unbind_num_trailing_slots,
1151
struct pipe_sampler_view **views)
1152
{
1153
struct v3d_context *v3d = v3d_context(pctx);
1154
struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader];
1155
unsigned i;
1156
unsigned new_nr = 0;
1157
1158
assert(start == 0);
1159
1160
for (i = 0; i < nr; i++) {
1161
if (views[i])
1162
new_nr = i + 1;
1163
pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
1164
}
1165
1166
for (; i < stage_tex->num_textures; i++) {
1167
pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
1168
}
1169
1170
stage_tex->num_textures = new_nr;
1171
1172
v3d_flag_dirty_sampler_state(v3d, shader);
1173
}
1174
1175
static struct pipe_stream_output_target *
1176
v3d_create_stream_output_target(struct pipe_context *pctx,
1177
struct pipe_resource *prsc,
1178
unsigned buffer_offset,
1179
unsigned buffer_size)
1180
{
1181
struct v3d_stream_output_target *target;
1182
1183
target = CALLOC_STRUCT(v3d_stream_output_target);
1184
if (!target)
1185
return NULL;
1186
1187
pipe_reference_init(&target->base.reference, 1);
1188
pipe_resource_reference(&target->base.buffer, prsc);
1189
1190
target->base.context = pctx;
1191
target->base.buffer_offset = buffer_offset;
1192
target->base.buffer_size = buffer_size;
1193
1194
return &target->base;
1195
}
1196
1197
static void
1198
v3d_stream_output_target_destroy(struct pipe_context *pctx,
1199
struct pipe_stream_output_target *target)
1200
{
1201
pipe_resource_reference(&target->buffer, NULL);
1202
free(target);
1203
}
1204
1205
static void
1206
v3d_set_stream_output_targets(struct pipe_context *pctx,
1207
unsigned num_targets,
1208
struct pipe_stream_output_target **targets,
1209
const unsigned *offsets)
1210
{
1211
struct v3d_context *ctx = v3d_context(pctx);
1212
struct v3d_streamout_stateobj *so = &ctx->streamout;
1213
unsigned i;
1214
1215
assert(num_targets <= ARRAY_SIZE(so->targets));
1216
1217
/* Update recorded vertex counts when we are ending the recording of
1218
* transform feedback. We do this when we switch primitive types
1219
* at draw time, but if we haven't switched primitives in our last
1220
* draw we need to do it here as well.
1221
*/
1222
if (num_targets == 0 && so->num_targets > 0)
1223
v3d_update_primitive_counters(ctx);
1224
1225
for (i = 0; i < num_targets; i++) {
1226
if (offsets[i] != -1)
1227
so->offsets[i] = offsets[i];
1228
1229
pipe_so_target_reference(&so->targets[i], targets[i]);
1230
}
1231
1232
for (; i < so->num_targets; i++)
1233
pipe_so_target_reference(&so->targets[i], NULL);
1234
1235
so->num_targets = num_targets;
1236
1237
/* Create primitive counters BO if needed */
1238
if (num_targets > 0 && !ctx->prim_counts) {
1239
/* Init all 7 counters and 1 padding to 0 */
1240
uint32_t zeroes[8] = { 0 };
1241
u_upload_data(ctx->uploader,
1242
0, sizeof(zeroes), 32, zeroes,
1243
&ctx->prim_counts_offset,
1244
&ctx->prim_counts);
1245
}
1246
1247
ctx->dirty |= V3D_DIRTY_STREAMOUT;
1248
}
1249
1250
static void
1251
v3d_set_shader_buffers(struct pipe_context *pctx,
1252
enum pipe_shader_type shader,
1253
unsigned start, unsigned count,
1254
const struct pipe_shader_buffer *buffers,
1255
unsigned writable_bitmask)
1256
{
1257
struct v3d_context *v3d = v3d_context(pctx);
1258
struct v3d_ssbo_stateobj *so = &v3d->ssbo[shader];
1259
unsigned mask = 0;
1260
1261
if (buffers) {
1262
for (unsigned i = 0; i < count; i++) {
1263
unsigned n = i + start;
1264
struct pipe_shader_buffer *buf = &so->sb[n];
1265
1266
if ((buf->buffer == buffers[i].buffer) &&
1267
(buf->buffer_offset == buffers[i].buffer_offset) &&
1268
(buf->buffer_size == buffers[i].buffer_size))
1269
continue;
1270
1271
mask |= 1 << n;
1272
1273
buf->buffer_offset = buffers[i].buffer_offset;
1274
buf->buffer_size = buffers[i].buffer_size;
1275
pipe_resource_reference(&buf->buffer, buffers[i].buffer);
1276
1277
if (buf->buffer)
1278
so->enabled_mask |= 1 << n;
1279
else
1280
so->enabled_mask &= ~(1 << n);
1281
}
1282
} else {
1283
mask = ((1 << count) - 1) << start;
1284
1285
for (unsigned i = 0; i < count; i++) {
1286
unsigned n = i + start;
1287
struct pipe_shader_buffer *buf = &so->sb[n];
1288
1289
pipe_resource_reference(&buf->buffer, NULL);
1290
}
1291
1292
so->enabled_mask &= ~mask;
1293
}
1294
1295
v3d->dirty |= V3D_DIRTY_SSBO;
1296
}
1297
1298
static void
1299
v3d_create_image_view_texture_shader_state(struct v3d_context *v3d,
1300
struct v3d_shaderimg_stateobj *so,
1301
int img)
1302
{
1303
#if V3D_VERSION >= 40
1304
struct v3d_image_view *iview = &so->si[img];
1305
1306
void *map;
1307
u_upload_alloc(v3d->uploader, 0, cl_packet_length(TEXTURE_SHADER_STATE),
1308
32,
1309
&iview->tex_state_offset,
1310
&iview->tex_state,
1311
&map);
1312
1313
struct pipe_resource *prsc = iview->base.resource;
1314
1315
v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
1316
v3d_setup_texture_shader_state(&tex, prsc,
1317
iview->base.u.tex.level,
1318
iview->base.u.tex.level,
1319
iview->base.u.tex.first_layer,
1320
iview->base.u.tex.last_layer);
1321
1322
tex.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X);
1323
tex.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y);
1324
tex.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z);
1325
tex.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W);
1326
1327
tex.texture_type = v3d_get_tex_format(&v3d->screen->devinfo,
1328
iview->base.format);
1329
};
1330
#else /* V3D_VERSION < 40 */
1331
/* V3D 3.x doesn't use support shader image load/store operations on
1332
* textures, so it would get lowered in the shader to general memory
1333
* acceses.
1334
*/
1335
#endif
1336
}
1337
1338
static void
1339
v3d_set_shader_images(struct pipe_context *pctx,
1340
enum pipe_shader_type shader,
1341
unsigned start, unsigned count,
1342
unsigned unbind_num_trailing_slots,
1343
const struct pipe_image_view *images)
1344
{
1345
struct v3d_context *v3d = v3d_context(pctx);
1346
struct v3d_shaderimg_stateobj *so = &v3d->shaderimg[shader];
1347
1348
if (images) {
1349
for (unsigned i = 0; i < count; i++) {
1350
unsigned n = i + start;
1351
struct v3d_image_view *iview = &so->si[n];
1352
1353
if ((iview->base.resource == images[i].resource) &&
1354
(iview->base.format == images[i].format) &&
1355
(iview->base.access == images[i].access) &&
1356
!memcmp(&iview->base.u, &images[i].u,
1357
sizeof(iview->base.u)))
1358
continue;
1359
1360
util_copy_image_view(&iview->base, &images[i]);
1361
1362
if (iview->base.resource) {
1363
so->enabled_mask |= 1 << n;
1364
v3d_create_image_view_texture_shader_state(v3d,
1365
so,
1366
n);
1367
} else {
1368
so->enabled_mask &= ~(1 << n);
1369
pipe_resource_reference(&iview->tex_state, NULL);
1370
}
1371
}
1372
} else {
1373
for (unsigned i = 0; i < count; i++) {
1374
unsigned n = i + start;
1375
struct v3d_image_view *iview = &so->si[n];
1376
1377
pipe_resource_reference(&iview->base.resource, NULL);
1378
pipe_resource_reference(&iview->tex_state, NULL);
1379
}
1380
1381
if (count == 32)
1382
so->enabled_mask = 0;
1383
else
1384
so->enabled_mask &= ~(((1 << count) - 1) << start);
1385
}
1386
1387
v3d->dirty |= V3D_DIRTY_SHADER_IMAGE;
1388
1389
if (unbind_num_trailing_slots) {
1390
v3d_set_shader_images(pctx, shader, start + count,
1391
unbind_num_trailing_slots, 0, NULL);
1392
}
1393
}
1394
1395
void
1396
v3dX(state_init)(struct pipe_context *pctx)
1397
{
1398
pctx->set_blend_color = v3d_set_blend_color;
1399
pctx->set_stencil_ref = v3d_set_stencil_ref;
1400
pctx->set_clip_state = v3d_set_clip_state;
1401
pctx->set_sample_mask = v3d_set_sample_mask;
1402
pctx->set_constant_buffer = v3d_set_constant_buffer;
1403
pctx->set_framebuffer_state = v3d_set_framebuffer_state;
1404
pctx->set_polygon_stipple = v3d_set_polygon_stipple;
1405
pctx->set_scissor_states = v3d_set_scissor_states;
1406
pctx->set_viewport_states = v3d_set_viewport_states;
1407
1408
pctx->set_vertex_buffers = v3d_set_vertex_buffers;
1409
1410
pctx->create_blend_state = v3d_create_blend_state;
1411
pctx->bind_blend_state = v3d_blend_state_bind;
1412
pctx->delete_blend_state = v3d_generic_cso_state_delete;
1413
1414
pctx->create_rasterizer_state = v3d_create_rasterizer_state;
1415
pctx->bind_rasterizer_state = v3d_rasterizer_state_bind;
1416
pctx->delete_rasterizer_state = v3d_generic_cso_state_delete;
1417
1418
pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state;
1419
pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind;
1420
pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete;
1421
1422
pctx->create_vertex_elements_state = v3d_vertex_state_create;
1423
pctx->delete_vertex_elements_state = v3d_vertex_state_delete;
1424
pctx->bind_vertex_elements_state = v3d_vertex_state_bind;
1425
1426
pctx->create_sampler_state = v3d_create_sampler_state;
1427
pctx->delete_sampler_state = v3d_sampler_state_delete;
1428
pctx->bind_sampler_states = v3d_sampler_states_bind;
1429
1430
pctx->create_sampler_view = v3d_create_sampler_view;
1431
pctx->sampler_view_destroy = v3d_sampler_view_destroy;
1432
pctx->set_sampler_views = v3d_set_sampler_views;
1433
1434
pctx->set_shader_buffers = v3d_set_shader_buffers;
1435
pctx->set_shader_images = v3d_set_shader_images;
1436
1437
pctx->create_stream_output_target = v3d_create_stream_output_target;
1438
pctx->stream_output_target_destroy = v3d_stream_output_target_destroy;
1439
pctx->set_stream_output_targets = v3d_set_stream_output_targets;
1440
}
1441
1442