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/common/v3d_util.h"
30 #include "broadcom/compiler/v3d_compiler.h"
31
32 static uint8_t
v3d_factor(enum pipe_blendfactor factor,bool dst_alpha_one)33 v3d_factor(enum pipe_blendfactor factor, bool dst_alpha_one)
34 {
35 /* We may get a bad blendfactor when blending is disabled. */
36 if (factor == 0)
37 return V3D_BLEND_FACTOR_ZERO;
38
39 switch (factor) {
40 case PIPE_BLENDFACTOR_ZERO:
41 return V3D_BLEND_FACTOR_ZERO;
42 case PIPE_BLENDFACTOR_ONE:
43 return V3D_BLEND_FACTOR_ONE;
44 case PIPE_BLENDFACTOR_SRC_COLOR:
45 return V3D_BLEND_FACTOR_SRC_COLOR;
46 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
47 return V3D_BLEND_FACTOR_INV_SRC_COLOR;
48 case PIPE_BLENDFACTOR_DST_COLOR:
49 return V3D_BLEND_FACTOR_DST_COLOR;
50 case PIPE_BLENDFACTOR_INV_DST_COLOR:
51 return V3D_BLEND_FACTOR_INV_DST_COLOR;
52 case PIPE_BLENDFACTOR_SRC_ALPHA:
53 return V3D_BLEND_FACTOR_SRC_ALPHA;
54 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
55 return V3D_BLEND_FACTOR_INV_SRC_ALPHA;
56 case PIPE_BLENDFACTOR_DST_ALPHA:
57 return (dst_alpha_one ?
58 V3D_BLEND_FACTOR_ONE :
59 V3D_BLEND_FACTOR_DST_ALPHA);
60 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
61 return (dst_alpha_one ?
62 V3D_BLEND_FACTOR_ZERO :
63 V3D_BLEND_FACTOR_INV_DST_ALPHA);
64 case PIPE_BLENDFACTOR_CONST_COLOR:
65 return V3D_BLEND_FACTOR_CONST_COLOR;
66 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
67 return V3D_BLEND_FACTOR_INV_CONST_COLOR;
68 case PIPE_BLENDFACTOR_CONST_ALPHA:
69 return V3D_BLEND_FACTOR_CONST_ALPHA;
70 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
71 return V3D_BLEND_FACTOR_INV_CONST_ALPHA;
72 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
73 return (dst_alpha_one ?
74 V3D_BLEND_FACTOR_ZERO :
75 V3D_BLEND_FACTOR_SRC_ALPHA_SATURATE);
76 default:
77 unreachable("Bad blend factor");
78 }
79 }
80
81 static uint32_t
translate_colormask(struct v3d_context * v3d,uint32_t colormask,int rt)82 translate_colormask(struct v3d_context *v3d, uint32_t colormask, int rt)
83 {
84 if (v3d->swap_color_rb & (1 << rt)) {
85 colormask = ((colormask & (2 | 8)) |
86 ((colormask & 1) << 2) |
87 ((colormask & 4) >> 2));
88 }
89
90 return (~colormask) & 0xf;
91 }
92
93 static void
emit_rt_blend(struct v3d_context * v3d,struct v3d_job * job,struct pipe_blend_state * blend,int rt,uint8_t rt_mask,bool blend_dst_alpha_one)94 emit_rt_blend(struct v3d_context *v3d, struct v3d_job *job,
95 struct pipe_blend_state *blend, int rt, uint8_t rt_mask,
96 bool blend_dst_alpha_one)
97 {
98 struct pipe_rt_blend_state *rtblend = &blend->rt[rt];
99
100 /* We don't need to emit blend state for disabled RTs. */
101 if (!rtblend->blend_enable)
102 return;
103
104 cl_emit(&job->bcl, BLEND_CFG, config) {
105 config.render_target_mask = rt_mask;
106
107 config.color_blend_mode = rtblend->rgb_func;
108 config.color_blend_dst_factor =
109 v3d_factor(rtblend->rgb_dst_factor,
110 blend_dst_alpha_one);
111 config.color_blend_src_factor =
112 v3d_factor(rtblend->rgb_src_factor,
113 blend_dst_alpha_one);
114
115 config.alpha_blend_mode = rtblend->alpha_func;
116 config.alpha_blend_dst_factor =
117 v3d_factor(rtblend->alpha_dst_factor,
118 blend_dst_alpha_one);
119 config.alpha_blend_src_factor =
120 v3d_factor(rtblend->alpha_src_factor,
121 blend_dst_alpha_one);
122 }
123 }
124
125 static void
emit_flat_shade_flags(struct v3d_job * job,int varying_offset,uint32_t varyings,enum V3DX (Varying_Flags_Action)lower,enum V3DX (Varying_Flags_Action)higher)126 emit_flat_shade_flags(struct v3d_job *job,
127 int varying_offset,
128 uint32_t varyings,
129 enum V3DX(Varying_Flags_Action) lower,
130 enum V3DX(Varying_Flags_Action) higher)
131 {
132 cl_emit(&job->bcl, FLAT_SHADE_FLAGS, flags) {
133 flags.varying_offset_v0 = varying_offset;
134 flags.flat_shade_flags_for_varyings_v024 = varyings;
135 flags.action_for_flat_shade_flags_of_lower_numbered_varyings =
136 lower;
137 flags.action_for_flat_shade_flags_of_higher_numbered_varyings =
138 higher;
139 }
140 }
141
142 static void
emit_noperspective_flags(struct v3d_job * job,int varying_offset,uint32_t varyings,enum V3DX (Varying_Flags_Action)lower,enum V3DX (Varying_Flags_Action)higher)143 emit_noperspective_flags(struct v3d_job *job,
144 int varying_offset,
145 uint32_t varyings,
146 enum V3DX(Varying_Flags_Action) lower,
147 enum V3DX(Varying_Flags_Action) higher)
148 {
149 cl_emit(&job->bcl, NON_PERSPECTIVE_FLAGS, flags) {
150 flags.varying_offset_v0 = varying_offset;
151 flags.non_perspective_flags_for_varyings_v024 = varyings;
152 flags.action_for_non_perspective_flags_of_lower_numbered_varyings =
153 lower;
154 flags.action_for_non_perspective_flags_of_higher_numbered_varyings =
155 higher;
156 }
157 }
158
159 static void
emit_centroid_flags(struct v3d_job * job,int varying_offset,uint32_t varyings,enum V3DX (Varying_Flags_Action)lower,enum V3DX (Varying_Flags_Action)higher)160 emit_centroid_flags(struct v3d_job *job,
161 int varying_offset,
162 uint32_t varyings,
163 enum V3DX(Varying_Flags_Action) lower,
164 enum V3DX(Varying_Flags_Action) higher)
165 {
166 cl_emit(&job->bcl, CENTROID_FLAGS, flags) {
167 flags.varying_offset_v0 = varying_offset;
168 flags.centroid_flags_for_varyings_v024 = varyings;
169 flags.action_for_centroid_flags_of_lower_numbered_varyings =
170 lower;
171 flags.action_for_centroid_flags_of_higher_numbered_varyings =
172 higher;
173 }
174 }
175
176 static bool
emit_varying_flags(struct v3d_job * job,uint32_t * flags,void (* flag_emit_callback)(struct v3d_job * job,int varying_offset,uint32_t flags,enum V3DX (Varying_Flags_Action)lower,enum V3DX (Varying_Flags_Action)higher))177 emit_varying_flags(struct v3d_job *job, uint32_t *flags,
178 void (*flag_emit_callback)(struct v3d_job *job,
179 int varying_offset,
180 uint32_t flags,
181 enum V3DX(Varying_Flags_Action) lower,
182 enum V3DX(Varying_Flags_Action) higher))
183 {
184 bool emitted_any = false;
185
186 for (int i = 0; i < ARRAY_SIZE(job->v3d->prog.fs->prog_data.fs->flat_shade_flags); i++) {
187 if (!flags[i])
188 continue;
189
190 if (emitted_any) {
191 flag_emit_callback(job, i, flags[i],
192 V3D_VARYING_FLAGS_ACTION_UNCHANGED,
193 V3D_VARYING_FLAGS_ACTION_UNCHANGED);
194 } else if (i == 0) {
195 flag_emit_callback(job, i, flags[i],
196 V3D_VARYING_FLAGS_ACTION_UNCHANGED,
197 V3D_VARYING_FLAGS_ACTION_ZEROED);
198 } else {
199 flag_emit_callback(job, i, flags[i],
200 V3D_VARYING_FLAGS_ACTION_ZEROED,
201 V3D_VARYING_FLAGS_ACTION_ZEROED);
202 }
203 emitted_any = true;
204 }
205
206 return emitted_any;
207 }
208
209 static inline struct v3d_uncompiled_shader *
get_tf_shader(struct v3d_context * v3d)210 get_tf_shader(struct v3d_context *v3d)
211 {
212 if (v3d->prog.bind_gs)
213 return v3d->prog.bind_gs;
214 else
215 return v3d->prog.bind_vs;
216 }
217
218 void
v3dX(emit_state)219 v3dX(emit_state)(struct pipe_context *pctx)
220 {
221 struct v3d_context *v3d = v3d_context(pctx);
222 struct v3d_job *job = v3d->job;
223 bool rasterizer_discard = v3d->rasterizer->base.rasterizer_discard;
224
225 if (v3d->dirty & (V3D_DIRTY_SCISSOR | V3D_DIRTY_VIEWPORT |
226 V3D_DIRTY_RASTERIZER)) {
227 float *vpscale = v3d->viewport.scale;
228 float *vptranslate = v3d->viewport.translate;
229 float vp_minx = -fabsf(vpscale[0]) + vptranslate[0];
230 float vp_maxx = fabsf(vpscale[0]) + vptranslate[0];
231 float vp_miny = -fabsf(vpscale[1]) + vptranslate[1];
232 float vp_maxy = fabsf(vpscale[1]) + vptranslate[1];
233
234 /* Clip to the scissor if it's enabled, but still clip to the
235 * drawable regardless since that controls where the binner
236 * tries to put things.
237 *
238 * Additionally, always clip the rendering to the viewport,
239 * since the hardware does guardband clipping, meaning
240 * primitives would rasterize outside of the view volume.
241 */
242 uint32_t minx, miny, maxx, maxy;
243 if (!v3d->rasterizer->base.scissor) {
244 minx = MAX2(vp_minx, 0);
245 miny = MAX2(vp_miny, 0);
246 maxx = MIN2(vp_maxx, job->draw_width);
247 maxy = MIN2(vp_maxy, job->draw_height);
248 } else {
249 minx = MAX2(vp_minx, v3d->scissor.minx);
250 miny = MAX2(vp_miny, v3d->scissor.miny);
251 maxx = MIN2(vp_maxx, v3d->scissor.maxx);
252 maxy = MIN2(vp_maxy, v3d->scissor.maxy);
253 }
254
255 cl_emit(&job->bcl, CLIP_WINDOW, clip) {
256 clip.clip_window_left_pixel_coordinate = minx;
257 clip.clip_window_bottom_pixel_coordinate = miny;
258 if (maxx > minx && maxy > miny) {
259 clip.clip_window_width_in_pixels = maxx - minx;
260 clip.clip_window_height_in_pixels = maxy - miny;
261 }
262 }
263
264 job->draw_min_x = MIN2(job->draw_min_x, minx);
265 job->draw_min_y = MIN2(job->draw_min_y, miny);
266 job->draw_max_x = MAX2(job->draw_max_x, maxx);
267 job->draw_max_y = MAX2(job->draw_max_y, maxy);
268
269 if (!v3d->rasterizer->base.scissor) {
270 job->scissor.disabled = true;
271 } else if (!job->scissor.disabled &&
272 (v3d->dirty & V3D_DIRTY_SCISSOR)) {
273 if (job->scissor.count < MAX_JOB_SCISSORS) {
274 job->scissor.rects[job->scissor.count].min_x =
275 v3d->scissor.minx;
276 job->scissor.rects[job->scissor.count].min_y =
277 v3d->scissor.miny;
278 job->scissor.rects[job->scissor.count].max_x =
279 v3d->scissor.maxx - 1;
280 job->scissor.rects[job->scissor.count].max_y =
281 v3d->scissor.maxy - 1;
282 job->scissor.count++;
283 } else {
284 job->scissor.disabled = true;
285 perf_debug("Too many scissor rects.");
286 }
287 }
288 }
289
290 if (v3d->dirty & (V3D_DIRTY_RASTERIZER |
291 V3D_DIRTY_ZSA |
292 V3D_DIRTY_BLEND |
293 V3D_DIRTY_COMPILED_FS)) {
294 cl_emit(&job->bcl, CFG_BITS, config) {
295 config.enable_forward_facing_primitive =
296 !rasterizer_discard &&
297 !(v3d->rasterizer->base.cull_face &
298 PIPE_FACE_FRONT);
299 config.enable_reverse_facing_primitive =
300 !rasterizer_discard &&
301 !(v3d->rasterizer->base.cull_face &
302 PIPE_FACE_BACK);
303 /* This seems backwards, but it's what gets the
304 * clipflat test to pass.
305 */
306 config.clockwise_primitives =
307 v3d->rasterizer->base.front_ccw;
308
309 config.enable_depth_offset =
310 v3d->rasterizer->base.offset_tri;
311
312 /* V3D follows GL behavior where the sample mask only
313 * applies when MSAA is enabled. Gallium has sample
314 * mask apply anyway, and the MSAA blit shaders will
315 * set sample mask without explicitly setting
316 * rasterizer oversample. Just force it on here,
317 * since the blit shaders are the only way to have
318 * !multisample && samplemask != 0xf.
319 */
320 config.rasterizer_oversample_mode =
321 v3d->rasterizer->base.multisample ||
322 v3d->sample_mask != 0xf;
323
324 config.direct3d_provoking_vertex =
325 v3d->rasterizer->base.flatshade_first;
326
327 config.blend_enable = v3d->blend->blend_enables;
328
329 /* Note: EZ state may update based on the compiled FS,
330 * along with ZSA
331 */
332 #if V3D_VERSION == 42
333 config.early_z_updates_enable =
334 (job->ez_state != V3D_EZ_DISABLED);
335 #endif
336 if (v3d->zsa->base.depth_enabled) {
337 config.z_updates_enable =
338 v3d->zsa->base.depth_writemask;
339 #if V3D_VERSION == 42
340 config.early_z_enable =
341 config.early_z_updates_enable;
342 #endif
343 config.depth_test_function =
344 v3d->zsa->base.depth_func;
345 } else {
346 config.depth_test_function = PIPE_FUNC_ALWAYS;
347 }
348
349 config.stencil_enable =
350 v3d->zsa->base.stencil[0].enabled;
351
352 /* Use nicer line caps when line smoothing is
353 * enabled
354 */
355 config.line_rasterization =
356 v3d_line_smoothing_enabled(v3d) ?
357 V3D_LINE_RASTERIZATION_PERP_END_CAPS :
358 V3D_LINE_RASTERIZATION_DIAMOND_EXIT;
359
360 if (config.enable_forward_facing_primitive &&
361 config.enable_reverse_facing_primitive &&
362 v3d->rasterizer->base.fill_front != v3d->rasterizer->base.fill_back) {
363 mesa_logw_once("Setting a different polygon mode for "
364 "front and back faces is not supported");
365 }
366
367 if (config.enable_forward_facing_primitive) {
368 if (v3d->rasterizer->base.fill_front != PIPE_POLYGON_MODE_FILL) {
369 config.direct3d_wireframe_triangles_mode = true;
370 config.direct3d_point_fill_mode =
371 v3d->rasterizer->base.fill_front == PIPE_POLYGON_MODE_POINT;
372 }
373 } else {
374 if (v3d->rasterizer->base.fill_back != PIPE_POLYGON_MODE_FILL) {
375 config.direct3d_wireframe_triangles_mode = true;
376 config.direct3d_point_fill_mode =
377 v3d->rasterizer->base.fill_back == PIPE_POLYGON_MODE_POINT;
378 }
379 }
380
381 #if V3D_VERSION >= 71
382 config.z_clipping_mode = v3d->rasterizer->base.depth_clip_near ||
383 v3d->rasterizer->base.depth_clip_far ?
384 V3D_Z_CLIP_MODE_MIN_ONE_TO_ONE : V3D_Z_CLIP_MODE_NONE;
385
386 config.z_clamp_mode = v3d->rasterizer->base.depth_clamp;
387 #endif
388 }
389 }
390
391 if (v3d->dirty & V3D_DIRTY_RASTERIZER &&
392 v3d->rasterizer->base.offset_tri) {
393 if (v3d->screen->devinfo.ver == 42 &&
394 job->zsbuf &&
395 job->zsbuf->format == PIPE_FORMAT_Z16_UNORM) {
396 cl_emit_prepacked_sized(&job->bcl,
397 v3d->rasterizer->depth_offset_z16,
398 cl_packet_length(DEPTH_OFFSET));
399 } else {
400 cl_emit_prepacked_sized(&job->bcl,
401 v3d->rasterizer->depth_offset,
402 cl_packet_length(DEPTH_OFFSET));
403 }
404 }
405
406 if (v3d->dirty & V3D_DIRTY_RASTERIZER) {
407 cl_emit(&job->bcl, POINT_SIZE, point_size) {
408 point_size.point_size = v3d->rasterizer->point_size;
409 }
410
411 cl_emit(&job->bcl, LINE_WIDTH, line_width) {
412 line_width.line_width = v3d_get_real_line_width(v3d);
413 }
414 }
415
416 if (v3d->dirty & V3D_DIRTY_VIEWPORT) {
417 #if V3D_VERSION == 42
418 cl_emit(&job->bcl, CLIPPER_XY_SCALING, clip) {
419 clip.viewport_half_width_in_1_256th_of_pixel =
420 v3d->viewport.scale[0] * 256.0f;
421 clip.viewport_half_height_in_1_256th_of_pixel =
422 v3d->viewport.scale[1] * 256.0f;
423 }
424 #endif
425 #if V3D_VERSION >= 71
426 cl_emit(&job->bcl, CLIPPER_XY_SCALING, clip) {
427 clip.viewport_half_width_in_1_64th_of_pixel =
428 v3d->viewport.scale[0] * 64.0f;
429 clip.viewport_half_height_in_1_64th_of_pixel =
430 v3d->viewport.scale[1] * 64.0f;
431 }
432 #endif
433
434
435 cl_emit(&job->bcl, CLIPPER_Z_SCALE_AND_OFFSET, clip) {
436 clip.viewport_z_offset_zc_to_zs =
437 v3d->viewport.translate[2];
438 clip.viewport_z_scale_zc_to_zs =
439 v3d->viewport.scale[2];
440 }
441 cl_emit(&job->bcl, CLIPPER_Z_MIN_MAX_CLIPPING_PLANES, clip) {
442 float z1 = (v3d->viewport.translate[2] -
443 v3d->viewport.scale[2]);
444 float z2 = (v3d->viewport.translate[2] +
445 v3d->viewport.scale[2]);
446 clip.minimum_zw = MIN2(z1, z2);
447 clip.maximum_zw = MAX2(z1, z2);
448 }
449
450 cl_emit(&job->bcl, VIEWPORT_OFFSET, vp) {
451 float vp_fine_x = v3d->viewport.translate[0];
452 float vp_fine_y = v3d->viewport.translate[1];
453 int32_t vp_coarse_x = 0;
454 int32_t vp_coarse_y = 0;
455
456 /* The fine coordinates must be unsigned, but coarse
457 * can be signed.
458 */
459 if (unlikely(vp_fine_x < 0)) {
460 int32_t blocks_64 =
461 DIV_ROUND_UP(fabsf(vp_fine_x), 64);
462 vp_fine_x += 64.0f * blocks_64;
463 vp_coarse_x -= blocks_64;
464 }
465
466 if (unlikely(vp_fine_y < 0)) {
467 int32_t blocks_64 =
468 DIV_ROUND_UP(fabsf(vp_fine_y), 64);
469 vp_fine_y += 64.0f * blocks_64;
470 vp_coarse_y -= blocks_64;
471 }
472
473 vp.fine_x = vp_fine_x;
474 vp.fine_y = vp_fine_y;
475 vp.coarse_x = vp_coarse_x;
476 vp.coarse_y = vp_coarse_y;
477 }
478 }
479
480 if (v3d->dirty & V3D_DIRTY_BLEND) {
481 struct v3d_blend_state *blend = v3d->blend;
482
483 if (blend->blend_enables) {
484 cl_emit(&job->bcl, BLEND_ENABLES, enables) {
485 enables.mask = blend->blend_enables;
486 }
487
488 const uint32_t max_rts =
489 V3D_MAX_RENDER_TARGETS(v3d->screen->devinfo.ver);
490 if (blend->base.independent_blend_enable) {
491 for (int i = 0; i < max_rts; i++)
492 emit_rt_blend(v3d, job, &blend->base, i,
493 (1 << i),
494 v3d->blend_dst_alpha_one & (1 << i));
495 } else if (v3d->blend_dst_alpha_one &&
496 util_bitcount(v3d->blend_dst_alpha_one) < job->nr_cbufs) {
497 /* Even if we don't have independent per-RT
498 * blending, we may have a combination of RT
499 * formats were some RTs have an alpha channel
500 * and others don't. Since this affects how
501 * blending is performed, we also need to emit
502 * independent blend configurations in this
503 * case: one for RTs with alpha and one for
504 * RTs without.
505 */
506 emit_rt_blend(v3d, job, &blend->base, 0,
507 ((1 << max_rts) - 1) &
508 v3d->blend_dst_alpha_one,
509 true);
510 emit_rt_blend(v3d, job, &blend->base, 0,
511 ((1 << max_rts) - 1) &
512 ~v3d->blend_dst_alpha_one,
513 false);
514 } else {
515 emit_rt_blend(v3d, job, &blend->base, 0,
516 (1 << max_rts) - 1,
517 v3d->blend_dst_alpha_one);
518 }
519 }
520 }
521
522 if (v3d->dirty & V3D_DIRTY_BLEND) {
523 struct pipe_blend_state *blend = &v3d->blend->base;
524
525 const uint32_t max_rts =
526 V3D_MAX_RENDER_TARGETS(v3d->screen->devinfo.ver);
527 cl_emit(&job->bcl, COLOR_WRITE_MASKS, mask) {
528 for (int i = 0; i < max_rts; i++) {
529 int rt = blend->independent_blend_enable ? i : 0;
530 int rt_mask = blend->rt[rt].colormask;
531
532 mask.mask |= translate_colormask(v3d, rt_mask,
533 i) << (4 * i);
534 }
535 }
536 }
537
538 /* GFXH-1431: On V3D 3.x, writing BLEND_CONFIG resets the constant
539 * color.
540 */
541 if (v3d->dirty & V3D_DIRTY_BLEND_COLOR) {
542 cl_emit(&job->bcl, BLEND_CONSTANT_COLOR, color) {
543 color.red_f16 = (v3d->swap_color_rb ?
544 v3d->blend_color.hf[2] :
545 v3d->blend_color.hf[0]);
546 color.green_f16 = v3d->blend_color.hf[1];
547 color.blue_f16 = (v3d->swap_color_rb ?
548 v3d->blend_color.hf[0] :
549 v3d->blend_color.hf[2]);
550 color.alpha_f16 = v3d->blend_color.hf[3];
551 }
552 }
553
554 if (v3d->dirty & (V3D_DIRTY_ZSA | V3D_DIRTY_STENCIL_REF)) {
555 struct pipe_stencil_state *front = &v3d->zsa->base.stencil[0];
556 struct pipe_stencil_state *back = &v3d->zsa->base.stencil[1];
557
558 if (front->enabled) {
559 cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,
560 v3d->zsa->stencil_front, config) {
561 config.stencil_ref_value =
562 v3d->stencil_ref.ref_value[0];
563 }
564 }
565
566 if (back->enabled) {
567 cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,
568 v3d->zsa->stencil_back, config) {
569 config.stencil_ref_value =
570 v3d->stencil_ref.ref_value[1];
571 }
572 }
573 }
574
575 if (v3d->dirty & V3D_DIRTY_FLAT_SHADE_FLAGS) {
576 if (!emit_varying_flags(job,
577 v3d->prog.fs->prog_data.fs->flat_shade_flags,
578 emit_flat_shade_flags)) {
579 cl_emit(&job->bcl, ZERO_ALL_FLAT_SHADE_FLAGS, flags);
580 }
581 }
582
583 if (v3d->dirty & V3D_DIRTY_NOPERSPECTIVE_FLAGS) {
584 if (!emit_varying_flags(job,
585 v3d->prog.fs->prog_data.fs->noperspective_flags,
586 emit_noperspective_flags)) {
587 cl_emit(&job->bcl, ZERO_ALL_NON_PERSPECTIVE_FLAGS, flags);
588 }
589 }
590
591 if (v3d->dirty & V3D_DIRTY_CENTROID_FLAGS) {
592 if (!emit_varying_flags(job,
593 v3d->prog.fs->prog_data.fs->centroid_flags,
594 emit_centroid_flags)) {
595 cl_emit(&job->bcl, ZERO_ALL_CENTROID_FLAGS, flags);
596 }
597 }
598
599 /* Set up the transform feedback data specs (which VPM entries to
600 * output to which buffers).
601 */
602 if (v3d->dirty & (V3D_DIRTY_STREAMOUT |
603 V3D_DIRTY_RASTERIZER |
604 V3D_DIRTY_PRIM_MODE)) {
605 struct v3d_streamout_stateobj *so = &v3d->streamout;
606 if (so->num_targets) {
607 bool psiz_per_vertex = (v3d->prim_mode == MESA_PRIM_POINTS &&
608 v3d->rasterizer->base.point_size_per_vertex);
609 struct v3d_uncompiled_shader *tf_shader =
610 get_tf_shader(v3d);
611 uint16_t *tf_specs = (psiz_per_vertex ?
612 tf_shader->tf_specs_psiz :
613 tf_shader->tf_specs);
614
615 bool tf_enabled = v3d_transform_feedback_enabled(v3d);
616 job->tf_enabled |= tf_enabled;
617
618 cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) {
619 tfe.number_of_16_bit_output_data_specs_following =
620 tf_shader->num_tf_specs;
621 tfe.enable = tf_enabled;
622 };
623 for (int i = 0; i < tf_shader->num_tf_specs; i++) {
624 cl_emit_prepacked(&job->bcl, &tf_specs[i]);
625 }
626 } else {
627 cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) {
628 tfe.enable = false;
629 };
630 }
631 }
632
633 /* Set up the transform feedback buffers. */
634 if (v3d->dirty & V3D_DIRTY_STREAMOUT) {
635 struct v3d_uncompiled_shader *tf_shader = get_tf_shader(v3d);
636 struct v3d_streamout_stateobj *so = &v3d->streamout;
637 for (int i = 0; i < so->num_targets; i++) {
638 struct pipe_stream_output_target *target =
639 so->targets[i];
640 struct v3d_resource *rsc = target ?
641 v3d_resource(target->buffer) : NULL;
642 struct pipe_shader_state *ss = &tf_shader->base;
643 struct pipe_stream_output_info *info = &ss->stream_output;
644 uint32_t offset = target ?
645 v3d_stream_output_target(target)->offset * info->stride[i] * 4 : 0;
646
647 if (!target)
648 continue;
649
650 cl_emit(&job->bcl, TRANSFORM_FEEDBACK_BUFFER, output) {
651 output.buffer_address =
652 cl_address(rsc->bo,
653 target->buffer_offset +
654 offset);
655 output.buffer_size_in_32_bit_words =
656 (target->buffer_size - offset) >> 2;
657 output.buffer_number = i;
658 }
659 if (target) {
660 v3d_job_add_tf_write_resource(v3d->job,
661 target->buffer);
662 }
663 /* XXX: buffer_size? */
664 }
665 }
666
667 if (v3d->dirty & V3D_DIRTY_OQ) {
668 cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter) {
669 if (v3d->active_queries && v3d->current_oq) {
670 counter.address = cl_address(v3d->current_oq, 0);
671 }
672 }
673 }
674
675 if (v3d->dirty & V3D_DIRTY_SAMPLE_STATE) {
676 cl_emit(&job->bcl, SAMPLE_STATE, state) {
677 /* Note: SampleCoverage was handled at the
678 * frontend level by converting to sample_mask.
679 */
680 state.coverage = 1.0;
681 state.mask = job->msaa ? v3d->sample_mask : 0xf;
682 }
683 }
684 }
685