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