Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/v3d/v3dx_emit.c
4570 views
1
/*
2
* Copyright © 2014-2017 Broadcom
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
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
#include "util/format/u_format.h"
25
#include "util/half_float.h"
26
#include "v3d_context.h"
27
#include "broadcom/common/v3d_macros.h"
28
#include "broadcom/cle/v3dx_pack.h"
29
#include "broadcom/compiler/v3d_compiler.h"
30
31
static uint8_t
32
v3d_factor(enum pipe_blendfactor factor, bool dst_alpha_one)
33
{
34
/* We may get a bad blendfactor when blending is disabled. */
35
if (factor == 0)
36
return V3D_BLEND_FACTOR_ZERO;
37
38
switch (factor) {
39
case PIPE_BLENDFACTOR_ZERO:
40
return V3D_BLEND_FACTOR_ZERO;
41
case PIPE_BLENDFACTOR_ONE:
42
return V3D_BLEND_FACTOR_ONE;
43
case PIPE_BLENDFACTOR_SRC_COLOR:
44
return V3D_BLEND_FACTOR_SRC_COLOR;
45
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
46
return V3D_BLEND_FACTOR_INV_SRC_COLOR;
47
case PIPE_BLENDFACTOR_DST_COLOR:
48
return V3D_BLEND_FACTOR_DST_COLOR;
49
case PIPE_BLENDFACTOR_INV_DST_COLOR:
50
return V3D_BLEND_FACTOR_INV_DST_COLOR;
51
case PIPE_BLENDFACTOR_SRC_ALPHA:
52
return V3D_BLEND_FACTOR_SRC_ALPHA;
53
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
54
return V3D_BLEND_FACTOR_INV_SRC_ALPHA;
55
case PIPE_BLENDFACTOR_DST_ALPHA:
56
return (dst_alpha_one ?
57
V3D_BLEND_FACTOR_ONE :
58
V3D_BLEND_FACTOR_DST_ALPHA);
59
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
60
return (dst_alpha_one ?
61
V3D_BLEND_FACTOR_ZERO :
62
V3D_BLEND_FACTOR_INV_DST_ALPHA);
63
case PIPE_BLENDFACTOR_CONST_COLOR:
64
return V3D_BLEND_FACTOR_CONST_COLOR;
65
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
66
return V3D_BLEND_FACTOR_INV_CONST_COLOR;
67
case PIPE_BLENDFACTOR_CONST_ALPHA:
68
return V3D_BLEND_FACTOR_CONST_ALPHA;
69
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
70
return V3D_BLEND_FACTOR_INV_CONST_ALPHA;
71
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
72
return (dst_alpha_one ?
73
V3D_BLEND_FACTOR_ZERO :
74
V3D_BLEND_FACTOR_SRC_ALPHA_SATURATE);
75
default:
76
unreachable("Bad blend factor");
77
}
78
}
79
80
static inline uint16_t
81
swizzled_border_color(const struct v3d_device_info *devinfo,
82
struct pipe_sampler_state *sampler,
83
struct v3d_sampler_view *sview,
84
int chan)
85
{
86
const struct util_format_description *desc =
87
util_format_description(sview->base.format);
88
uint8_t swiz = chan;
89
90
/* If we're doing swizzling in the sampler, then only rearrange the
91
* border color for the mismatch between the V3D texture format and
92
* the PIPE_FORMAT, since GL_ARB_texture_swizzle will be handled by
93
* the sampler's swizzle.
94
*
95
* For swizzling in the shader, we don't do any pre-swizzling of the
96
* border color.
97
*/
98
if (v3d_get_tex_return_size(devinfo, sview->base.format,
99
sampler->compare_mode) != 32)
100
swiz = desc->swizzle[swiz];
101
102
switch (swiz) {
103
case PIPE_SWIZZLE_0:
104
return _mesa_float_to_half(0.0);
105
case PIPE_SWIZZLE_1:
106
return _mesa_float_to_half(1.0);
107
default:
108
return _mesa_float_to_half(sampler->border_color.f[swiz]);
109
}
110
}
111
112
#if V3D_VERSION < 40
113
static uint32_t
114
translate_swizzle(unsigned char pipe_swizzle)
115
{
116
switch (pipe_swizzle) {
117
case PIPE_SWIZZLE_0:
118
return 0;
119
case PIPE_SWIZZLE_1:
120
return 1;
121
case PIPE_SWIZZLE_X:
122
case PIPE_SWIZZLE_Y:
123
case PIPE_SWIZZLE_Z:
124
case PIPE_SWIZZLE_W:
125
return 2 + pipe_swizzle;
126
default:
127
unreachable("unknown swizzle");
128
}
129
}
130
131
static void
132
emit_one_texture(struct v3d_context *v3d, struct v3d_texture_stateobj *stage_tex,
133
int i)
134
{
135
struct v3d_job *job = v3d->job;
136
struct pipe_sampler_state *psampler = stage_tex->samplers[i];
137
struct v3d_sampler_state *sampler = v3d_sampler_state(psampler);
138
struct pipe_sampler_view *psview = stage_tex->textures[i];
139
struct v3d_sampler_view *sview = v3d_sampler_view(psview);
140
struct pipe_resource *prsc = psview->texture;
141
struct v3d_resource *rsc = v3d_resource(prsc);
142
const struct v3d_device_info *devinfo = &v3d->screen->devinfo;
143
144
stage_tex->texture_state[i].offset =
145
v3d_cl_ensure_space(&job->indirect,
146
cl_packet_length(TEXTURE_SHADER_STATE),
147
32);
148
v3d_bo_set_reference(&stage_tex->texture_state[i].bo,
149
job->indirect.bo);
150
151
uint32_t return_size = v3d_get_tex_return_size(devinfo, psview->format,
152
psampler->compare_mode);
153
154
struct V3D33_TEXTURE_SHADER_STATE unpacked = {
155
/* XXX */
156
.border_color_red = swizzled_border_color(devinfo, psampler,
157
sview, 0),
158
.border_color_green = swizzled_border_color(devinfo, psampler,
159
sview, 1),
160
.border_color_blue = swizzled_border_color(devinfo, psampler,
161
sview, 2),
162
.border_color_alpha = swizzled_border_color(devinfo, psampler,
163
sview, 3),
164
165
/* In the normal texturing path, the LOD gets clamped between
166
* min/max, and the base_level field (set in the sampler view
167
* from first_level) only decides where the min/mag switch
168
* happens, so we need to use the LOD clamps to keep us
169
* between min and max.
170
*
171
* For txf, the LOD clamp is still used, despite GL not
172
* wanting that. We will need to have a separate
173
* TEXTURE_SHADER_STATE that ignores psview->min/max_lod to
174
* support txf properly.
175
*/
176
.min_level_of_detail = MIN2(psview->u.tex.first_level +
177
MAX2(psampler->min_lod, 0),
178
psview->u.tex.last_level),
179
.max_level_of_detail = MIN2(psview->u.tex.first_level +
180
MAX2(psampler->max_lod,
181
psampler->min_lod),
182
psview->u.tex.last_level),
183
184
.texture_base_pointer = cl_address(rsc->bo,
185
rsc->slices[0].offset),
186
187
.output_32_bit = return_size == 32,
188
};
189
190
/* Set up the sampler swizzle if we're doing 16-bit sampling. For
191
* 32-bit, we leave swizzling up to the shader compiler.
192
*
193
* Note: Contrary to the docs, the swizzle still applies even if the
194
* return size is 32. It's just that you probably want to swizzle in
195
* the shader, because you need the Y/Z/W channels to be defined.
196
*/
197
if (return_size == 32) {
198
unpacked.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X);
199
unpacked.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y);
200
unpacked.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z);
201
unpacked.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W);
202
} else {
203
unpacked.swizzle_r = translate_swizzle(sview->swizzle[0]);
204
unpacked.swizzle_g = translate_swizzle(sview->swizzle[1]);
205
unpacked.swizzle_b = translate_swizzle(sview->swizzle[2]);
206
unpacked.swizzle_a = translate_swizzle(sview->swizzle[3]);
207
}
208
209
int min_img_filter = psampler->min_img_filter;
210
int min_mip_filter = psampler->min_mip_filter;
211
int mag_img_filter = psampler->mag_img_filter;
212
213
if (return_size == 32) {
214
min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
215
min_img_filter = PIPE_TEX_FILTER_NEAREST;
216
mag_img_filter = PIPE_TEX_FILTER_NEAREST;
217
}
218
219
bool min_nearest = min_img_filter == PIPE_TEX_FILTER_NEAREST;
220
switch (min_mip_filter) {
221
case PIPE_TEX_MIPFILTER_NONE:
222
unpacked.filter += min_nearest ? 2 : 0;
223
break;
224
case PIPE_TEX_MIPFILTER_NEAREST:
225
unpacked.filter += min_nearest ? 4 : 8;
226
break;
227
case PIPE_TEX_MIPFILTER_LINEAR:
228
unpacked.filter += min_nearest ? 4 : 8;
229
unpacked.filter += 2;
230
break;
231
}
232
233
if (mag_img_filter == PIPE_TEX_FILTER_NEAREST)
234
unpacked.filter++;
235
236
if (psampler->max_anisotropy > 8)
237
unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_16_1;
238
else if (psampler->max_anisotropy > 4)
239
unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_8_1;
240
else if (psampler->max_anisotropy > 2)
241
unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_4_1;
242
else if (psampler->max_anisotropy)
243
unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_2_1;
244
245
uint8_t packed[cl_packet_length(TEXTURE_SHADER_STATE)];
246
cl_packet_pack(TEXTURE_SHADER_STATE)(&job->indirect, packed, &unpacked);
247
248
for (int i = 0; i < ARRAY_SIZE(packed); i++)
249
packed[i] |= sview->texture_shader_state[i] | sampler->texture_shader_state[i];
250
251
/* TMU indirect structs need to be 32b aligned. */
252
v3d_cl_ensure_space(&job->indirect, ARRAY_SIZE(packed), 32);
253
cl_emit_prepacked(&job->indirect, &packed);
254
}
255
256
static void
257
emit_textures(struct v3d_context *v3d, struct v3d_texture_stateobj *stage_tex)
258
{
259
for (int i = 0; i < stage_tex->num_textures; i++) {
260
if (stage_tex->textures[i])
261
emit_one_texture(v3d, stage_tex, i);
262
}
263
}
264
#endif /* V3D_VERSION < 40 */
265
266
static uint32_t
267
translate_colormask(struct v3d_context *v3d, uint32_t colormask, int rt)
268
{
269
if (v3d->swap_color_rb & (1 << rt)) {
270
colormask = ((colormask & (2 | 8)) |
271
((colormask & 1) << 2) |
272
((colormask & 4) >> 2));
273
}
274
275
return (~colormask) & 0xf;
276
}
277
278
static void
279
emit_rt_blend(struct v3d_context *v3d, struct v3d_job *job,
280
struct pipe_blend_state *blend, int rt)
281
{
282
struct pipe_rt_blend_state *rtblend = &blend->rt[rt];
283
284
#if V3D_VERSION >= 40
285
/* We don't need to emit blend state for disabled RTs. */
286
if (!rtblend->blend_enable)
287
return;
288
#endif
289
290
cl_emit(&job->bcl, BLEND_CFG, config) {
291
#if V3D_VERSION >= 40
292
if (blend->independent_blend_enable)
293
config.render_target_mask = 1 << rt;
294
else
295
config.render_target_mask = (1 << V3D_MAX_DRAW_BUFFERS) - 1;
296
#else
297
assert(rt == 0);
298
#endif
299
300
config.color_blend_mode = rtblend->rgb_func;
301
config.color_blend_dst_factor =
302
v3d_factor(rtblend->rgb_dst_factor,
303
v3d->blend_dst_alpha_one);
304
config.color_blend_src_factor =
305
v3d_factor(rtblend->rgb_src_factor,
306
v3d->blend_dst_alpha_one);
307
308
config.alpha_blend_mode = rtblend->alpha_func;
309
config.alpha_blend_dst_factor =
310
v3d_factor(rtblend->alpha_dst_factor,
311
v3d->blend_dst_alpha_one);
312
config.alpha_blend_src_factor =
313
v3d_factor(rtblend->alpha_src_factor,
314
v3d->blend_dst_alpha_one);
315
}
316
}
317
318
static void
319
emit_flat_shade_flags(struct v3d_job *job,
320
int varying_offset,
321
uint32_t varyings,
322
enum V3DX(Varying_Flags_Action) lower,
323
enum V3DX(Varying_Flags_Action) higher)
324
{
325
cl_emit(&job->bcl, FLAT_SHADE_FLAGS, flags) {
326
flags.varying_offset_v0 = varying_offset;
327
flags.flat_shade_flags_for_varyings_v024 = varyings;
328
flags.action_for_flat_shade_flags_of_lower_numbered_varyings =
329
lower;
330
flags.action_for_flat_shade_flags_of_higher_numbered_varyings =
331
higher;
332
}
333
}
334
335
#if V3D_VERSION >= 40
336
static void
337
emit_noperspective_flags(struct v3d_job *job,
338
int varying_offset,
339
uint32_t varyings,
340
enum V3DX(Varying_Flags_Action) lower,
341
enum V3DX(Varying_Flags_Action) higher)
342
{
343
cl_emit(&job->bcl, NON_PERSPECTIVE_FLAGS, flags) {
344
flags.varying_offset_v0 = varying_offset;
345
flags.non_perspective_flags_for_varyings_v024 = varyings;
346
flags.action_for_non_perspective_flags_of_lower_numbered_varyings =
347
lower;
348
flags.action_for_non_perspective_flags_of_higher_numbered_varyings =
349
higher;
350
}
351
}
352
353
static void
354
emit_centroid_flags(struct v3d_job *job,
355
int varying_offset,
356
uint32_t varyings,
357
enum V3DX(Varying_Flags_Action) lower,
358
enum V3DX(Varying_Flags_Action) higher)
359
{
360
cl_emit(&job->bcl, CENTROID_FLAGS, flags) {
361
flags.varying_offset_v0 = varying_offset;
362
flags.centroid_flags_for_varyings_v024 = varyings;
363
flags.action_for_centroid_flags_of_lower_numbered_varyings =
364
lower;
365
flags.action_for_centroid_flags_of_higher_numbered_varyings =
366
higher;
367
}
368
}
369
#endif /* V3D_VERSION >= 40 */
370
371
static bool
372
emit_varying_flags(struct v3d_job *job, uint32_t *flags,
373
void (*flag_emit_callback)(struct v3d_job *job,
374
int varying_offset,
375
uint32_t flags,
376
enum V3DX(Varying_Flags_Action) lower,
377
enum V3DX(Varying_Flags_Action) higher))
378
{
379
struct v3d_context *v3d = job->v3d;
380
bool emitted_any = false;
381
382
for (int i = 0; i < ARRAY_SIZE(v3d->prog.fs->prog_data.fs->flat_shade_flags); i++) {
383
if (!flags[i])
384
continue;
385
386
if (emitted_any) {
387
flag_emit_callback(job, i, flags[i],
388
V3D_VARYING_FLAGS_ACTION_UNCHANGED,
389
V3D_VARYING_FLAGS_ACTION_UNCHANGED);
390
} else if (i == 0) {
391
flag_emit_callback(job, i, flags[i],
392
V3D_VARYING_FLAGS_ACTION_UNCHANGED,
393
V3D_VARYING_FLAGS_ACTION_ZEROED);
394
} else {
395
flag_emit_callback(job, i, flags[i],
396
V3D_VARYING_FLAGS_ACTION_ZEROED,
397
V3D_VARYING_FLAGS_ACTION_ZEROED);
398
}
399
emitted_any = true;
400
}
401
402
return emitted_any;
403
}
404
405
static inline struct v3d_uncompiled_shader *
406
get_tf_shader(struct v3d_context *v3d)
407
{
408
if (v3d->prog.bind_gs)
409
return v3d->prog.bind_gs;
410
else
411
return v3d->prog.bind_vs;
412
}
413
414
void
415
v3dX(emit_state)(struct pipe_context *pctx)
416
{
417
struct v3d_context *v3d = v3d_context(pctx);
418
struct v3d_job *job = v3d->job;
419
bool rasterizer_discard = v3d->rasterizer->base.rasterizer_discard;
420
421
if (v3d->dirty & (V3D_DIRTY_SCISSOR | V3D_DIRTY_VIEWPORT |
422
V3D_DIRTY_RASTERIZER)) {
423
float *vpscale = v3d->viewport.scale;
424
float *vptranslate = v3d->viewport.translate;
425
float vp_minx = -fabsf(vpscale[0]) + vptranslate[0];
426
float vp_maxx = fabsf(vpscale[0]) + vptranslate[0];
427
float vp_miny = -fabsf(vpscale[1]) + vptranslate[1];
428
float vp_maxy = fabsf(vpscale[1]) + vptranslate[1];
429
430
/* Clip to the scissor if it's enabled, but still clip to the
431
* drawable regardless since that controls where the binner
432
* tries to put things.
433
*
434
* Additionally, always clip the rendering to the viewport,
435
* since the hardware does guardband clipping, meaning
436
* primitives would rasterize outside of the view volume.
437
*/
438
uint32_t minx, miny, maxx, maxy;
439
if (!v3d->rasterizer->base.scissor) {
440
minx = MAX2(vp_minx, 0);
441
miny = MAX2(vp_miny, 0);
442
maxx = MIN2(vp_maxx, job->draw_width);
443
maxy = MIN2(vp_maxy, job->draw_height);
444
} else {
445
minx = MAX2(vp_minx, v3d->scissor.minx);
446
miny = MAX2(vp_miny, v3d->scissor.miny);
447
maxx = MIN2(vp_maxx, v3d->scissor.maxx);
448
maxy = MIN2(vp_maxy, v3d->scissor.maxy);
449
}
450
451
cl_emit(&job->bcl, CLIP_WINDOW, clip) {
452
clip.clip_window_left_pixel_coordinate = minx;
453
clip.clip_window_bottom_pixel_coordinate = miny;
454
if (maxx > minx && maxy > miny) {
455
clip.clip_window_width_in_pixels = maxx - minx;
456
clip.clip_window_height_in_pixels = maxy - miny;
457
} else if (V3D_VERSION < 41) {
458
/* The HW won't entirely clip out when scissor
459
* w/h is 0. Just treat it the same as
460
* rasterizer discard.
461
*/
462
rasterizer_discard = true;
463
clip.clip_window_width_in_pixels = 1;
464
clip.clip_window_height_in_pixels = 1;
465
}
466
}
467
468
job->draw_min_x = MIN2(job->draw_min_x, minx);
469
job->draw_min_y = MIN2(job->draw_min_y, miny);
470
job->draw_max_x = MAX2(job->draw_max_x, maxx);
471
job->draw_max_y = MAX2(job->draw_max_y, maxy);
472
473
if (!v3d->rasterizer->base.scissor) {
474
job->scissor.disabled = true;
475
} else if (!job->scissor.disabled &&
476
(v3d->dirty & V3D_DIRTY_SCISSOR)) {
477
if (job->scissor.count < MAX_JOB_SCISSORS) {
478
job->scissor.rects[job->scissor.count].min_x =
479
v3d->scissor.minx;
480
job->scissor.rects[job->scissor.count].min_y =
481
v3d->scissor.miny;
482
job->scissor.rects[job->scissor.count].max_x =
483
v3d->scissor.maxx - 1;
484
job->scissor.rects[job->scissor.count].max_y =
485
v3d->scissor.maxy - 1;
486
job->scissor.count++;
487
} else {
488
job->scissor.disabled = true;
489
perf_debug("Too many scissor rects.");
490
}
491
}
492
}
493
494
if (v3d->dirty & (V3D_DIRTY_RASTERIZER |
495
V3D_DIRTY_ZSA |
496
V3D_DIRTY_BLEND |
497
V3D_DIRTY_COMPILED_FS)) {
498
cl_emit(&job->bcl, CFG_BITS, config) {
499
config.enable_forward_facing_primitive =
500
!rasterizer_discard &&
501
!(v3d->rasterizer->base.cull_face &
502
PIPE_FACE_FRONT);
503
config.enable_reverse_facing_primitive =
504
!rasterizer_discard &&
505
!(v3d->rasterizer->base.cull_face &
506
PIPE_FACE_BACK);
507
/* This seems backwards, but it's what gets the
508
* clipflat test to pass.
509
*/
510
config.clockwise_primitives =
511
v3d->rasterizer->base.front_ccw;
512
513
config.enable_depth_offset =
514
v3d->rasterizer->base.offset_tri;
515
516
/* V3D follows GL behavior where the sample mask only
517
* applies when MSAA is enabled. Gallium has sample
518
* mask apply anyway, and the MSAA blit shaders will
519
* set sample mask without explicitly setting
520
* rasterizer oversample. Just force it on here,
521
* since the blit shaders are the only way to have
522
* !multisample && samplemask != 0xf.
523
*/
524
config.rasterizer_oversample_mode =
525
v3d->rasterizer->base.multisample ||
526
v3d->sample_mask != 0xf;
527
528
config.direct3d_provoking_vertex =
529
v3d->rasterizer->base.flatshade_first;
530
531
config.blend_enable = v3d->blend->blend_enables;
532
533
/* Note: EZ state may update based on the compiled FS,
534
* along with ZSA
535
*/
536
config.early_z_updates_enable =
537
(job->ez_state != V3D_EZ_DISABLED);
538
if (v3d->zsa->base.depth_enabled) {
539
config.z_updates_enable =
540
v3d->zsa->base.depth_writemask;
541
config.early_z_enable =
542
config.early_z_updates_enable;
543
config.depth_test_function =
544
v3d->zsa->base.depth_func;
545
} else {
546
config.depth_test_function = PIPE_FUNC_ALWAYS;
547
}
548
549
config.stencil_enable =
550
v3d->zsa->base.stencil[0].enabled;
551
552
/* Use nicer line caps when line smoothing is
553
* enabled
554
*/
555
config.line_rasterization =
556
v3d_line_smoothing_enabled(v3d) ? 1 : 0;
557
}
558
559
}
560
561
if (v3d->dirty & V3D_DIRTY_RASTERIZER &&
562
v3d->rasterizer->base.offset_tri) {
563
if (job->zsbuf &&
564
job->zsbuf->format == PIPE_FORMAT_Z16_UNORM) {
565
cl_emit_prepacked_sized(&job->bcl,
566
v3d->rasterizer->depth_offset_z16,
567
cl_packet_length(DEPTH_OFFSET));
568
} else {
569
cl_emit_prepacked_sized(&job->bcl,
570
v3d->rasterizer->depth_offset,
571
cl_packet_length(DEPTH_OFFSET));
572
}
573
}
574
575
if (v3d->dirty & V3D_DIRTY_RASTERIZER) {
576
cl_emit(&job->bcl, POINT_SIZE, point_size) {
577
point_size.point_size = v3d->rasterizer->point_size;
578
}
579
580
cl_emit(&job->bcl, LINE_WIDTH, line_width) {
581
line_width.line_width = v3d_get_real_line_width(v3d);
582
}
583
}
584
585
if (v3d->dirty & V3D_DIRTY_VIEWPORT) {
586
cl_emit(&job->bcl, CLIPPER_XY_SCALING, clip) {
587
clip.viewport_half_width_in_1_256th_of_pixel =
588
v3d->viewport.scale[0] * 256.0f;
589
clip.viewport_half_height_in_1_256th_of_pixel =
590
v3d->viewport.scale[1] * 256.0f;
591
}
592
593
cl_emit(&job->bcl, CLIPPER_Z_SCALE_AND_OFFSET, clip) {
594
clip.viewport_z_offset_zc_to_zs =
595
v3d->viewport.translate[2];
596
clip.viewport_z_scale_zc_to_zs =
597
v3d->viewport.scale[2];
598
}
599
cl_emit(&job->bcl, CLIPPER_Z_MIN_MAX_CLIPPING_PLANES, clip) {
600
float z1 = (v3d->viewport.translate[2] -
601
v3d->viewport.scale[2]);
602
float z2 = (v3d->viewport.translate[2] +
603
v3d->viewport.scale[2]);
604
clip.minimum_zw = MIN2(z1, z2);
605
clip.maximum_zw = MAX2(z1, z2);
606
}
607
608
cl_emit(&job->bcl, VIEWPORT_OFFSET, vp) {
609
vp.viewport_centre_x_coordinate =
610
v3d->viewport.translate[0];
611
vp.viewport_centre_y_coordinate =
612
v3d->viewport.translate[1];
613
}
614
}
615
616
if (v3d->dirty & V3D_DIRTY_BLEND) {
617
struct v3d_blend_state *blend = v3d->blend;
618
619
if (blend->blend_enables) {
620
#if V3D_VERSION >= 40
621
cl_emit(&job->bcl, BLEND_ENABLES, enables) {
622
enables.mask = blend->blend_enables;
623
}
624
#endif
625
626
if (blend->base.independent_blend_enable) {
627
for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++)
628
emit_rt_blend(v3d, job, &blend->base, i);
629
} else {
630
emit_rt_blend(v3d, job, &blend->base, 0);
631
}
632
}
633
}
634
635
if (v3d->dirty & V3D_DIRTY_BLEND) {
636
struct pipe_blend_state *blend = &v3d->blend->base;
637
638
cl_emit(&job->bcl, COLOR_WRITE_MASKS, mask) {
639
for (int i = 0; i < 4; i++) {
640
int rt = blend->independent_blend_enable ? i : 0;
641
int rt_mask = blend->rt[rt].colormask;
642
643
mask.mask |= translate_colormask(v3d, rt_mask,
644
i) << (4 * i);
645
}
646
}
647
}
648
649
/* GFXH-1431: On V3D 3.x, writing BLEND_CONFIG resets the constant
650
* color.
651
*/
652
if (v3d->dirty & V3D_DIRTY_BLEND_COLOR ||
653
(V3D_VERSION < 41 && (v3d->dirty & V3D_DIRTY_BLEND))) {
654
cl_emit(&job->bcl, BLEND_CONSTANT_COLOR, color) {
655
color.red_f16 = (v3d->swap_color_rb ?
656
v3d->blend_color.hf[2] :
657
v3d->blend_color.hf[0]);
658
color.green_f16 = v3d->blend_color.hf[1];
659
color.blue_f16 = (v3d->swap_color_rb ?
660
v3d->blend_color.hf[0] :
661
v3d->blend_color.hf[2]);
662
color.alpha_f16 = v3d->blend_color.hf[3];
663
}
664
}
665
666
if (v3d->dirty & (V3D_DIRTY_ZSA | V3D_DIRTY_STENCIL_REF)) {
667
struct pipe_stencil_state *front = &v3d->zsa->base.stencil[0];
668
struct pipe_stencil_state *back = &v3d->zsa->base.stencil[1];
669
670
if (front->enabled) {
671
cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,
672
v3d->zsa->stencil_front, config) {
673
config.stencil_ref_value =
674
v3d->stencil_ref.ref_value[0];
675
}
676
}
677
678
if (back->enabled) {
679
cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,
680
v3d->zsa->stencil_back, config) {
681
config.stencil_ref_value =
682
v3d->stencil_ref.ref_value[1];
683
}
684
}
685
}
686
687
#if V3D_VERSION < 40
688
/* Pre-4.x, we have texture state that depends on both the sampler and
689
* the view, so we merge them together at draw time.
690
*/
691
if (v3d->dirty & V3D_DIRTY_FRAGTEX)
692
emit_textures(v3d, &v3d->tex[PIPE_SHADER_FRAGMENT]);
693
694
if (v3d->dirty & V3D_DIRTY_GEOMTEX)
695
emit_textures(v3d, &v3d->tex[PIPE_SHADER_GEOMETRY]);
696
697
if (v3d->dirty & V3D_DIRTY_VERTTEX)
698
emit_textures(v3d, &v3d->tex[PIPE_SHADER_VERTEX]);
699
#endif
700
701
if (v3d->dirty & V3D_DIRTY_FLAT_SHADE_FLAGS) {
702
if (!emit_varying_flags(job,
703
v3d->prog.fs->prog_data.fs->flat_shade_flags,
704
emit_flat_shade_flags)) {
705
cl_emit(&job->bcl, ZERO_ALL_FLAT_SHADE_FLAGS, flags);
706
}
707
}
708
709
#if V3D_VERSION >= 40
710
if (v3d->dirty & V3D_DIRTY_NOPERSPECTIVE_FLAGS) {
711
if (!emit_varying_flags(job,
712
v3d->prog.fs->prog_data.fs->noperspective_flags,
713
emit_noperspective_flags)) {
714
cl_emit(&job->bcl, ZERO_ALL_NON_PERSPECTIVE_FLAGS, flags);
715
}
716
}
717
718
if (v3d->dirty & V3D_DIRTY_CENTROID_FLAGS) {
719
if (!emit_varying_flags(job,
720
v3d->prog.fs->prog_data.fs->centroid_flags,
721
emit_centroid_flags)) {
722
cl_emit(&job->bcl, ZERO_ALL_CENTROID_FLAGS, flags);
723
}
724
}
725
#endif
726
727
/* Set up the transform feedback data specs (which VPM entries to
728
* output to which buffers).
729
*/
730
if (v3d->dirty & (V3D_DIRTY_STREAMOUT |
731
V3D_DIRTY_RASTERIZER |
732
V3D_DIRTY_PRIM_MODE)) {
733
struct v3d_streamout_stateobj *so = &v3d->streamout;
734
if (so->num_targets) {
735
bool psiz_per_vertex = (v3d->prim_mode == PIPE_PRIM_POINTS &&
736
v3d->rasterizer->base.point_size_per_vertex);
737
struct v3d_uncompiled_shader *tf_shader =
738
get_tf_shader(v3d);
739
uint16_t *tf_specs = (psiz_per_vertex ?
740
tf_shader->tf_specs_psiz :
741
tf_shader->tf_specs);
742
743
#if V3D_VERSION >= 40
744
bool tf_enabled = v3d_transform_feedback_enabled(v3d);
745
job->tf_enabled |= tf_enabled;
746
747
cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) {
748
tfe.number_of_16_bit_output_data_specs_following =
749
tf_shader->num_tf_specs;
750
tfe.enable = tf_enabled;
751
};
752
#else /* V3D_VERSION < 40 */
753
cl_emit(&job->bcl, TRANSFORM_FEEDBACK_ENABLE, tfe) {
754
tfe.number_of_32_bit_output_buffer_address_following =
755
so->num_targets;
756
tfe.number_of_16_bit_output_data_specs_following =
757
tf_shader->num_tf_specs;
758
};
759
#endif /* V3D_VERSION < 40 */
760
for (int i = 0; i < tf_shader->num_tf_specs; i++) {
761
cl_emit_prepacked(&job->bcl, &tf_specs[i]);
762
}
763
} else {
764
#if V3D_VERSION >= 40
765
cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) {
766
tfe.enable = false;
767
};
768
#endif /* V3D_VERSION >= 40 */
769
}
770
}
771
772
/* Set up the transform feedback buffers. */
773
if (v3d->dirty & V3D_DIRTY_STREAMOUT) {
774
struct v3d_uncompiled_shader *tf_shader = get_tf_shader(v3d);
775
struct v3d_streamout_stateobj *so = &v3d->streamout;
776
for (int i = 0; i < so->num_targets; i++) {
777
const struct pipe_stream_output_target *target =
778
so->targets[i];
779
struct v3d_resource *rsc = target ?
780
v3d_resource(target->buffer) : NULL;
781
struct pipe_shader_state *ss = &tf_shader->base;
782
struct pipe_stream_output_info *info = &ss->stream_output;
783
uint32_t offset = (v3d->streamout.offsets[i] *
784
info->stride[i] * 4);
785
786
#if V3D_VERSION >= 40
787
if (!target)
788
continue;
789
790
cl_emit(&job->bcl, TRANSFORM_FEEDBACK_BUFFER, output) {
791
output.buffer_address =
792
cl_address(rsc->bo,
793
target->buffer_offset +
794
offset);
795
output.buffer_size_in_32_bit_words =
796
(target->buffer_size - offset) >> 2;
797
output.buffer_number = i;
798
}
799
#else /* V3D_VERSION < 40 */
800
cl_emit(&job->bcl, TRANSFORM_FEEDBACK_OUTPUT_ADDRESS, output) {
801
if (target) {
802
output.address =
803
cl_address(rsc->bo,
804
target->buffer_offset +
805
offset);
806
}
807
};
808
#endif /* V3D_VERSION < 40 */
809
if (target) {
810
v3d_job_add_tf_write_resource(v3d->job,
811
target->buffer);
812
}
813
/* XXX: buffer_size? */
814
}
815
}
816
817
if (v3d->dirty & V3D_DIRTY_OQ) {
818
cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter) {
819
if (v3d->active_queries && v3d->current_oq) {
820
counter.address = cl_address(v3d->current_oq, 0);
821
}
822
}
823
}
824
825
#if V3D_VERSION >= 40
826
if (v3d->dirty & V3D_DIRTY_SAMPLE_STATE) {
827
cl_emit(&job->bcl, SAMPLE_STATE, state) {
828
/* Note: SampleCoverage was handled at the
829
* frontend level by converting to sample_mask.
830
*/
831
state.coverage = 1.0;
832
state.mask = job->msaa ? v3d->sample_mask : 0xf;
833
}
834
}
835
#endif
836
}
837
838