1 /*
2 * Copyright © 2014-2017 Broadcom
3 * Copyright (C) 2012 Rob Clark <[email protected]>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "pipe/p_state.h"
26 #include "util/format/u_format.h"
27 #include "util/u_framebuffer.h"
28 #include "util/u_inlines.h"
29 #include "util/u_math.h"
30 #include "util/u_memory.h"
31 #include "util/half_float.h"
32 #include "util/u_helpers.h"
33 #include "util/u_upload_mgr.h"
34
35 #include "v3d_context.h"
36 #include "broadcom/common/v3d_tiling.h"
37 #include "broadcom/common/v3d_macros.h"
38 #include "broadcom/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 assert(BITSET_SIZE(so->enabled_mask) <= 32);
301 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask[0], vb,
302 count, true);
303
304 so->count = BITSET_LAST_BIT(so->enabled_mask);
305
306 v3d->dirty |= V3D_DIRTY_VTXBUF;
307 }
308
309 static void
v3d_blend_state_bind(struct pipe_context * pctx,void * hwcso)310 v3d_blend_state_bind(struct pipe_context *pctx, void *hwcso)
311 {
312 struct v3d_context *v3d = v3d_context(pctx);
313 v3d->blend = hwcso;
314 v3d->dirty |= V3D_DIRTY_BLEND;
315 }
316
317 static void
v3d_rasterizer_state_bind(struct pipe_context * pctx,void * hwcso)318 v3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
319 {
320 struct v3d_context *v3d = v3d_context(pctx);
321 v3d->rasterizer = hwcso;
322 v3d->dirty |= V3D_DIRTY_RASTERIZER;
323 }
324
325 static void
v3d_zsa_state_bind(struct pipe_context * pctx,void * hwcso)326 v3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
327 {
328 struct v3d_context *v3d = v3d_context(pctx);
329 v3d->zsa = hwcso;
330 v3d->dirty |= V3D_DIRTY_ZSA;
331 }
332
333
334 static bool
needs_default_attribute_values(void)335 needs_default_attribute_values(void)
336 {
337 #if V3D_VERSION == 42
338 /* FIXME: on vulkan we are able to refine even further, as we know in
339 * advance when we create the pipeline if we have an integer vertex
340 * attrib. Pending to check if we could do something similar here.
341 */
342 return true;
343 #endif
344 return false;
345 }
346
347 static void *
v3d_vertex_state_create(struct pipe_context * pctx,unsigned num_elements,const struct pipe_vertex_element * elements)348 v3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
349 const struct pipe_vertex_element *elements)
350 {
351 struct v3d_context *v3d = v3d_context(pctx);
352 struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj);
353
354 if (!so)
355 return NULL;
356
357 memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
358 so->num_elements = num_elements;
359
360 for (int i = 0; i < so->num_elements; i++) {
361 const struct pipe_vertex_element *elem = &elements[i];
362 const struct util_format_description *desc =
363 util_format_description(elem->src_format);
364 uint32_t r_size = desc->channel[0].size;
365
366 const uint32_t size =
367 cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);
368
369 v3dx_pack(&so->attrs[i * size],
370 GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) {
371 /* vec_size == 0 means 4 */
372 attr.vec_size = desc->nr_channels & 3;
373 attr.signed_int_type = (desc->channel[0].type ==
374 UTIL_FORMAT_TYPE_SIGNED);
375
376 attr.normalized_int_type = desc->channel[0].normalized;
377 attr.read_as_int_uint = desc->channel[0].pure_integer;
378 attr.instance_divisor = MIN2(elem->instance_divisor,
379 V3D_MAX_VERTEX_ATTRIB_DIVISOR);
380
381 switch (desc->channel[0].type) {
382 case UTIL_FORMAT_TYPE_FLOAT:
383 if (r_size == 32) {
384 attr.type = ATTRIBUTE_FLOAT;
385 } else {
386 assert(r_size == 16);
387 attr.type = ATTRIBUTE_HALF_FLOAT;
388 }
389 break;
390
391 case UTIL_FORMAT_TYPE_SIGNED:
392 case UTIL_FORMAT_TYPE_UNSIGNED:
393 switch (r_size) {
394 case 32:
395 attr.type = ATTRIBUTE_INT;
396 break;
397 case 16:
398 attr.type = ATTRIBUTE_SHORT;
399 break;
400 case 10:
401 attr.type = ATTRIBUTE_INT2_10_10_10;
402 break;
403 case 8:
404 attr.type = ATTRIBUTE_BYTE;
405 break;
406 default:
407 fprintf(stderr,
408 "format %s unsupported\n",
409 desc->name);
410 attr.type = ATTRIBUTE_BYTE;
411 abort();
412 }
413 break;
414
415 default:
416 fprintf(stderr,
417 "format %s unsupported\n",
418 desc->name);
419 abort();
420 }
421 }
422 }
423
424 if (needs_default_attribute_values()) {
425 /* Set up the default attribute values in case any of the vertex
426 * elements use them.
427 */
428 uint32_t *attrs;
429 u_upload_alloc(v3d->state_uploader, 0,
430 V3D_MAX_VS_INPUTS * sizeof(float), 16,
431 &so->defaults_offset, &so->defaults, (void **)&attrs);
432
433 for (int i = 0; i < V3D_MAX_VS_INPUTS / 4; i++) {
434 attrs[i * 4 + 0] = 0;
435 attrs[i * 4 + 1] = 0;
436 attrs[i * 4 + 2] = 0;
437 if (i < so->num_elements &&
438 util_format_is_pure_integer(so->pipe[i].src_format)) {
439 attrs[i * 4 + 3] = 1;
440 } else {
441 attrs[i * 4 + 3] = fui(1.0);
442 }
443 }
444 } else {
445 so->defaults = NULL;
446 so->defaults_offset = 0;
447 }
448
449 u_upload_unmap(v3d->state_uploader);
450 return so;
451 }
452
453 static void
v3d_vertex_state_delete(struct pipe_context * pctx,void * hwcso)454 v3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso)
455 {
456 struct v3d_vertex_stateobj *so = hwcso;
457
458 pipe_resource_reference(&so->defaults, NULL);
459 free(so);
460 }
461
462 static void
v3d_vertex_state_bind(struct pipe_context * pctx,void * hwcso)463 v3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
464 {
465 struct v3d_context *v3d = v3d_context(pctx);
466 v3d->vtx = hwcso;
467 v3d->dirty |= V3D_DIRTY_VTXSTATE;
468 }
469
470 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)471 v3d_set_constant_buffer(struct pipe_context *pctx, enum pipe_shader_type shader, uint index,
472 bool take_ownership,
473 const struct pipe_constant_buffer *cb)
474 {
475 struct v3d_context *v3d = v3d_context(pctx);
476 struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader];
477
478 util_copy_constant_buffer(&so->cb[index], cb, take_ownership);
479
480 /* Note that the gallium frontend can unbind constant buffers by
481 * passing NULL here.
482 */
483 if (unlikely(!cb)) {
484 BITSET_CLEAR(so->enabled_mask, index);
485 BITSET_CLEAR(so->dirty_mask, index);
486 return;
487 }
488
489 BITSET_SET(so->enabled_mask, index);
490 BITSET_SET(so->dirty_mask, index);
491 v3d->dirty |= V3D_DIRTY_CONSTBUF;
492 }
493
494 static void
v3d_set_framebuffer_state(struct pipe_context * pctx,const struct pipe_framebuffer_state * framebuffer)495 v3d_set_framebuffer_state(struct pipe_context *pctx,
496 const struct pipe_framebuffer_state *framebuffer)
497 {
498 struct v3d_context *v3d = v3d_context(pctx);
499 struct pipe_framebuffer_state *cso = &v3d->framebuffer;
500
501 v3d->job = NULL;
502
503 util_copy_framebuffer_state(cso, framebuffer);
504
505 v3d->swap_color_rb = 0;
506 v3d->blend_dst_alpha_one = 0;
507 for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) {
508 struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i];
509 if (!cbuf)
510 continue;
511
512 const struct util_format_description *desc =
513 util_format_description(cbuf->format);
514
515 if (desc->swizzle[3] == PIPE_SWIZZLE_1)
516 v3d->blend_dst_alpha_one |= 1 << i;
517 }
518
519 v3d->dirty |= V3D_DIRTY_FRAMEBUFFER;
520 }
521
V3DX(Wrap_Mode)522 static enum V3DX(Wrap_Mode)
523 translate_wrap(uint32_t pipe_wrap)
524 {
525 switch (pipe_wrap) {
526 case PIPE_TEX_WRAP_REPEAT:
527 return V3D_WRAP_MODE_REPEAT;
528 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
529 return V3D_WRAP_MODE_CLAMP;
530 case PIPE_TEX_WRAP_MIRROR_REPEAT:
531 return V3D_WRAP_MODE_MIRROR;
532 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
533 return V3D_WRAP_MODE_BORDER;
534 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
535 return V3D_WRAP_MODE_MIRROR_ONCE;
536 default:
537 unreachable("Unknown wrap mode");
538 }
539 }
540
541 static void
v3d_upload_sampler_state_variant(void * map,const struct pipe_sampler_state * cso,enum v3d_sampler_state_variant variant)542 v3d_upload_sampler_state_variant(void *map,
543 const struct pipe_sampler_state *cso,
544 enum v3d_sampler_state_variant variant)
545 {
546 v3dx_pack(map, SAMPLER_STATE, sampler) {
547 sampler.wrap_i_border = false;
548
549 sampler.wrap_s = translate_wrap(cso->wrap_s);
550 sampler.wrap_t = translate_wrap(cso->wrap_t);
551 sampler.wrap_r = translate_wrap(cso->wrap_r);
552
553 sampler.fixed_bias = cso->lod_bias;
554 sampler.depth_compare_function = cso->compare_mode ?
555 cso->compare_func :
556 V3D_COMPARE_FUNC_NEVER;
557 sampler.min_filter_nearest =
558 cso->min_img_filter == PIPE_TEX_FILTER_NEAREST;
559 sampler.mag_filter_nearest =
560 cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST;
561 sampler.mip_filter_nearest =
562 cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR;
563
564 sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod),
565 15);
566 sampler.max_level_of_detail = MIN2(MAX2(cso->max_lod,
567 cso->min_lod), 15);
568
569 /* If we're not doing inter-miplevel filtering, we need to
570 * clamp the LOD so that we only sample from baselevel.
571 * However, we need to still allow the calculated LOD to be
572 * fractionally over the baselevel, so that the HW can decide
573 * between the min and mag filters.
574 */
575 if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
576 sampler.min_level_of_detail =
577 MIN2(sampler.min_level_of_detail, 1.0 / 256.0);
578 sampler.max_level_of_detail =
579 MIN2(sampler.max_level_of_detail, 1.0 / 256.0);
580 }
581
582 if (cso->max_anisotropy) {
583 sampler.anisotropy_enable = true;
584
585 if (cso->max_anisotropy > 8)
586 sampler.maximum_anisotropy = 3;
587 else if (cso->max_anisotropy > 4)
588 sampler.maximum_anisotropy = 2;
589 else if (cso->max_anisotropy > 2)
590 sampler.maximum_anisotropy = 1;
591 }
592
593 if (variant == V3D_SAMPLER_STATE_BORDER_0000) {
594 sampler.border_color_mode = V3D_BORDER_COLOR_0000;
595 } else if (variant == V3D_SAMPLER_STATE_BORDER_0001) {
596 sampler.border_color_mode = V3D_BORDER_COLOR_0001;
597 } else if (variant == V3D_SAMPLER_STATE_BORDER_1111) {
598 sampler.border_color_mode = V3D_BORDER_COLOR_1111;
599 } else {
600 sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS;
601
602 union pipe_color_union border;
603
604 /* First, reswizzle the border color for any
605 * mismatching we're doing between the texture's
606 * channel order in hardware (R) versus what it is at
607 * the GL level (ALPHA)
608 */
609 switch (variant) {
610 case V3D_SAMPLER_STATE_F16_BGRA:
611 case V3D_SAMPLER_STATE_F16_BGRA_UNORM:
612 case V3D_SAMPLER_STATE_F16_BGRA_SNORM:
613 border.i[0] = cso->border_color.i[2];
614 border.i[1] = cso->border_color.i[1];
615 border.i[2] = cso->border_color.i[0];
616 border.i[3] = cso->border_color.i[3];
617 break;
618
619 case V3D_SAMPLER_STATE_F16_A:
620 case V3D_SAMPLER_STATE_F16_A_UNORM:
621 case V3D_SAMPLER_STATE_F16_A_SNORM:
622 case V3D_SAMPLER_STATE_32_A:
623 case V3D_SAMPLER_STATE_32_A_UNORM:
624 case V3D_SAMPLER_STATE_32_A_SNORM:
625 border.i[0] = cso->border_color.i[3];
626 border.i[1] = 0;
627 border.i[2] = 0;
628 border.i[3] = 0;
629 break;
630
631 case V3D_SAMPLER_STATE_F16_LA:
632 case V3D_SAMPLER_STATE_F16_LA_UNORM:
633 case V3D_SAMPLER_STATE_F16_LA_SNORM:
634 border.i[0] = cso->border_color.i[0];
635 border.i[1] = cso->border_color.i[3];
636 border.i[2] = 0;
637 border.i[3] = 0;
638 break;
639
640 default:
641 border = cso->border_color;
642 }
643
644 /* Perform any clamping. */
645 switch (variant) {
646 case V3D_SAMPLER_STATE_F16_UNORM:
647 case V3D_SAMPLER_STATE_F16_BGRA_UNORM:
648 case V3D_SAMPLER_STATE_F16_A_UNORM:
649 case V3D_SAMPLER_STATE_F16_LA_UNORM:
650 case V3D_SAMPLER_STATE_32_UNORM:
651 case V3D_SAMPLER_STATE_32_A_UNORM:
652 for (int i = 0; i < 4; i++)
653 border.f[i] = CLAMP(border.f[i], 0, 1);
654 break;
655
656 case V3D_SAMPLER_STATE_F16_SNORM:
657 case V3D_SAMPLER_STATE_F16_BGRA_SNORM:
658 case V3D_SAMPLER_STATE_F16_A_SNORM:
659 case V3D_SAMPLER_STATE_F16_LA_SNORM:
660 case V3D_SAMPLER_STATE_32_SNORM:
661 case V3D_SAMPLER_STATE_32_A_SNORM:
662 for (int i = 0; i < 4; i++)
663 border.f[i] = CLAMP(border.f[i], -1, 1);
664 break;
665
666 case V3D_SAMPLER_STATE_1010102U:
667 border.ui[0] = CLAMP(border.ui[0],
668 0, (1 << 10) - 1);
669 border.ui[1] = CLAMP(border.ui[1],
670 0, (1 << 10) - 1);
671 border.ui[2] = CLAMP(border.ui[2],
672 0, (1 << 10) - 1);
673 border.ui[3] = CLAMP(border.ui[3],
674 0, 3);
675 break;
676
677 case V3D_SAMPLER_STATE_16U:
678 for (int i = 0; i < 4; i++)
679 border.ui[i] = CLAMP(border.ui[i],
680 0, 0xffff);
681 break;
682
683 case V3D_SAMPLER_STATE_16I:
684 for (int i = 0; i < 4; i++)
685 border.i[i] = CLAMP(border.i[i],
686 -32768, 32767);
687 break;
688
689 case V3D_SAMPLER_STATE_8U:
690 for (int i = 0; i < 4; i++)
691 border.ui[i] = CLAMP(border.ui[i],
692 0, 0xff);
693 break;
694
695 case V3D_SAMPLER_STATE_8I:
696 for (int i = 0; i < 4; i++)
697 border.i[i] = CLAMP(border.i[i],
698 -128, 127);
699 break;
700
701 default:
702 break;
703 }
704
705 #if V3D_VERSION == 42
706 /* The TMU in V3D 7.x always takes 32-bit floats and handles conversions
707 * for us. In V3D 4.x we need to manually convert floating point color
708 * values to the expected format.
709 */
710 if (variant < V3D_SAMPLER_STATE_32) {
711 border.ui[0] = _mesa_float_to_half(border.f[0]);
712 border.ui[1] = _mesa_float_to_half(border.f[1]);
713 border.ui[2] = _mesa_float_to_half(border.f[2]);
714 border.ui[3] = _mesa_float_to_half(border.f[3]);
715 }
716 #endif
717 sampler.border_color_word_0 = border.ui[0];
718 sampler.border_color_word_1 = border.ui[1];
719 sampler.border_color_word_2 = border.ui[2];
720 sampler.border_color_word_3 = border.ui[3];
721 }
722 }
723 }
724
725 static void *
v3d_create_sampler_state(struct pipe_context * pctx,const struct pipe_sampler_state * cso)726 v3d_create_sampler_state(struct pipe_context *pctx,
727 const struct pipe_sampler_state *cso)
728 {
729 UNUSED struct v3d_context *v3d = v3d_context(pctx);
730 struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state);
731
732 if (!so)
733 return NULL;
734
735 memcpy(so, cso, sizeof(*cso));
736
737 enum V3DX(Wrap_Mode) wrap_s = translate_wrap(cso->wrap_s);
738 enum V3DX(Wrap_Mode) wrap_t = translate_wrap(cso->wrap_t);
739 enum V3DX(Wrap_Mode) wrap_r = translate_wrap(cso->wrap_r);
740
741 bool uses_border_color = (wrap_s == V3D_WRAP_MODE_BORDER ||
742 wrap_t == V3D_WRAP_MODE_BORDER ||
743 wrap_r == V3D_WRAP_MODE_BORDER);
744
745 so->border_color_variants = false;
746
747 /* This is the variant with the default hardware settings */
748 enum v3d_sampler_state_variant border_variant = V3D_SAMPLER_STATE_BORDER_0000;
749
750 if (uses_border_color) {
751 if (cso->border_color.ui[0] == 0 &&
752 cso->border_color.ui[1] == 0 &&
753 cso->border_color.ui[2] == 0 &&
754 cso->border_color.ui[3] == 0) {
755 border_variant = V3D_SAMPLER_STATE_BORDER_0000;
756 } else if (cso->border_color.ui[0] == 0 &&
757 cso->border_color.ui[1] == 0 &&
758 cso->border_color.ui[2] == 0 &&
759 cso->border_color.ui[3] == 0x3F800000) {
760 border_variant = V3D_SAMPLER_STATE_BORDER_0001;
761 } else if (cso->border_color.ui[0] == 0x3F800000 &&
762 cso->border_color.ui[1] == 0x3F800000 &&
763 cso->border_color.ui[2] == 0x3F800000 &&
764 cso->border_color.ui[3] == 0x3F800000) {
765 border_variant = V3D_SAMPLER_STATE_BORDER_1111;
766 } else {
767 so->border_color_variants = true;
768 }
769 }
770
771 void *map;
772 int sampler_align = so->border_color_variants ? 32 : 8;
773 int sampler_size = align(cl_packet_length(SAMPLER_STATE), sampler_align);
774 int num_variants = (so->border_color_variants ? ARRAY_SIZE(so->sampler_state_offset) : 1);
775 u_upload_alloc(v3d->state_uploader, 0,
776 sampler_size * num_variants,
777 sampler_align,
778 &so->sampler_state_offset[0],
779 &so->sampler_state,
780 &map);
781
782 for (int i = 0; i < num_variants; i++) {
783 so->sampler_state_offset[i] =
784 so->sampler_state_offset[0] + i * sampler_size;
785 v3d_upload_sampler_state_variant(map + i * sampler_size,
786 cso,
787 so->border_color_variants ? i : border_variant);
788 }
789
790 return so;
791 }
792
793 static void
v3d_sampler_states_bind(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned nr,void ** hwcso)794 v3d_sampler_states_bind(struct pipe_context *pctx,
795 enum pipe_shader_type shader, unsigned start,
796 unsigned nr, void **hwcso)
797 {
798 struct v3d_context *v3d = v3d_context(pctx);
799 struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader];
800
801 assert(start == 0);
802 unsigned i;
803 unsigned new_nr = 0;
804
805 for (i = 0; i < nr; i++) {
806 if (hwcso[i])
807 new_nr = i + 1;
808 stage_tex->samplers[i] = hwcso[i];
809 }
810
811 for (; i < stage_tex->num_samplers; i++) {
812 stage_tex->samplers[i] = NULL;
813 }
814
815 stage_tex->num_samplers = new_nr;
816
817 v3d_flag_dirty_sampler_state(v3d, shader);
818 }
819
820 static void
v3d_sampler_state_delete(struct pipe_context * pctx,void * hwcso)821 v3d_sampler_state_delete(struct pipe_context *pctx,
822 void *hwcso)
823 {
824 struct pipe_sampler_state *psampler = hwcso;
825 struct v3d_sampler_state *sampler = v3d_sampler_state(psampler);
826
827 pipe_resource_reference(&sampler->sampler_state, NULL);
828 free(psampler);
829 }
830
831 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)832 v3d_setup_texture_shader_state_from_buffer(struct V3DX(TEXTURE_SHADER_STATE) *tex,
833 struct pipe_resource *prsc,
834 enum pipe_format format,
835 unsigned offset,
836 unsigned size)
837 {
838 struct v3d_resource *rsc = v3d_resource(prsc);
839
840 tex->image_depth = 1;
841 tex->image_width = size / util_format_get_blocksize(format);
842
843 /* On 4.x, the height of a 1D texture is redefined to be the
844 * upper 14 bits of the width (which is only usable with txf).
845 */
846 tex->image_height = tex->image_width >> 14;
847
848 tex->image_width &= (1 << 14) - 1;
849 tex->image_height &= (1 << 14) - 1;
850
851 /* Note that we don't have a job to reference the texture's sBO
852 * at state create time, so any time this sampler view is used
853 * we need to add the texture to the job.
854 */
855 tex->texture_base_pointer =
856 cl_address(NULL, rsc->bo->offset + offset);
857 }
858
859 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)860 v3d_setup_texture_shader_state(const struct v3d_device_info *devinfo,
861 struct V3DX(TEXTURE_SHADER_STATE) *tex,
862 struct pipe_resource *prsc,
863 int base_level, int last_level,
864 int first_layer, int last_layer,
865 bool sampling_cube_array)
866 {
867 /* Due to ARB_texture_view, a cubemap array can be seen as 2D texture
868 * array.
869 */
870 assert(!sampling_cube_array ||
871 prsc->target == PIPE_TEXTURE_CUBE_ARRAY ||
872 prsc->target == PIPE_TEXTURE_2D_ARRAY);
873
874 struct v3d_resource *rsc = v3d_resource(prsc);
875 int msaa_scale = prsc->nr_samples > 1 ? 2 : 1;
876
877 tex->image_width = prsc->width0 * msaa_scale;
878 tex->image_height = prsc->height0 * msaa_scale;
879
880 /* On 4.x, the height of a 1D texture is redefined to be the
881 * upper 14 bits of the width (which is only usable with txf).
882 */
883 if (prsc->target == PIPE_TEXTURE_1D ||
884 prsc->target == PIPE_TEXTURE_1D_ARRAY) {
885 tex->image_height = tex->image_width >> 14;
886 }
887
888 tex->image_width &= (1 << 14) - 1;
889 tex->image_height &= (1 << 14) - 1;
890
891 if (prsc->target == PIPE_TEXTURE_3D) {
892 tex->image_depth = prsc->depth0;
893 } else {
894 tex->image_depth = (last_layer - first_layer) + 1;
895 }
896
897 /* Empirical testing with CTS shows that when we are sampling from
898 * cube arrays we want to set image depth to layers / 6, but not when
899 * doing image load/store or sampling from 2d image arrays.
900 */
901 if (sampling_cube_array) {
902 assert(tex->image_depth % 6 == 0);
903 tex->image_depth /= 6;
904 }
905
906 tex->base_level = base_level;
907
908 tex->max_level = last_level;
909 /* Note that we don't have a job to reference the texture's sBO
910 * at state create time, so any time this sampler view is used
911 * we need to add the texture to the job.
912 */
913 const uint32_t base_offset = rsc->bo->offset +
914 v3d_layer_offset(prsc, 0, first_layer);
915
916 tex->texture_base_pointer = cl_address(NULL, base_offset);
917 tex->array_stride_64_byte_aligned = rsc->cube_map_stride / 64;
918
919 #if V3D_VERSION >= 71
920 tex->chroma_offset_x = 1;
921 tex->chroma_offset_y = 1;
922 /* See comment in XML field definition for rationale of the shifts */
923 tex->texture_base_pointer_cb = base_offset >> 6;
924 tex->texture_base_pointer_cr = base_offset >> 6;
925 #endif
926
927 /* Since other platform devices may produce UIF images even
928 * when they're not big enough for V3D to assume they're UIF,
929 * we force images with level 0 as UIF to be always treated
930 * that way.
931 */
932 tex->level_0_is_strictly_uif =
933 (rsc->slices[0].tiling == V3D_TILING_UIF_XOR ||
934 rsc->slices[0].tiling == V3D_TILING_UIF_NO_XOR);
935 tex->level_0_xor_enable = (rsc->slices[0].tiling == V3D_TILING_UIF_XOR);
936
937 if (tex->level_0_is_strictly_uif)
938 tex->level_0_ub_pad = rsc->slices[0].ub_pad;
939
940 if (tex->uif_xor_disable ||
941 tex->level_0_is_strictly_uif) {
942 tex->extended = true;
943 }
944 }
945
946 void
v3dX(create_texture_shader_state_bo)947 v3dX(create_texture_shader_state_bo)(struct v3d_context *v3d,
948 struct v3d_sampler_view *so)
949 {
950 struct pipe_resource *prsc = so->texture;
951 struct v3d_resource *rsc = v3d_resource(prsc);
952 const struct pipe_sampler_view *cso = &so->base;
953 struct v3d_screen *screen = v3d->screen;
954
955 void *map;
956
957 assert(so->serial_id != rsc->serial_id);
958
959 v3d_bo_unreference(&so->bo);
960 so->bo = v3d_bo_alloc(v3d->screen,
961 cl_packet_length(TEXTURE_SHADER_STATE), "sampler");
962 map = v3d_bo_map(so->bo);
963
964 v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
965 if (prsc->target != PIPE_BUFFER) {
966 v3d_setup_texture_shader_state(&v3d->screen->devinfo,
967 &tex, prsc,
968 cso->u.tex.first_level,
969 cso->u.tex.last_level,
970 cso->u.tex.first_layer,
971 cso->u.tex.last_layer,
972 cso->target == PIPE_TEXTURE_CUBE_ARRAY);
973 } else {
974 v3d_setup_texture_shader_state_from_buffer(&tex, prsc,
975 cso->format,
976 cso->u.buf.offset,
977 cso->u.buf.size);
978 }
979
980 bool is_srgb = util_format_is_srgb(cso->format);
981 #if V3D_VERSION == 42
982 tex.srgb = is_srgb;
983 #endif
984 #if V3D_VERSION >= 71
985 tex.transfer_func = is_srgb ? TRANSFER_FUNC_SRGB : TRANSFER_FUNC_NONE;
986 #endif
987
988 tex.swizzle_r = v3d_translate_pipe_swizzle(so->swizzle[0]);
989 tex.swizzle_g = v3d_translate_pipe_swizzle(so->swizzle[1]);
990 tex.swizzle_b = v3d_translate_pipe_swizzle(so->swizzle[2]);
991 tex.swizzle_a = v3d_translate_pipe_swizzle(so->swizzle[3]);
992
993 tex.texture_type = v3d_get_tex_format(&screen->devinfo,
994 cso->format);
995 };
996
997 so->serial_id = rsc->serial_id;
998 }
999
1000 static struct pipe_sampler_view *
v3d_create_sampler_view(struct pipe_context * pctx,struct pipe_resource * prsc,const struct pipe_sampler_view * cso)1001 v3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
1002 const struct pipe_sampler_view *cso)
1003 {
1004 struct v3d_context *v3d = v3d_context(pctx);
1005 struct v3d_screen *screen = v3d->screen;
1006 struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view);
1007 struct v3d_resource *rsc = v3d_resource(prsc);
1008
1009 if (!so)
1010 return NULL;
1011
1012 so->base = *cso;
1013
1014 pipe_reference(NULL, &prsc->reference);
1015
1016 /* Compute the sampler view's swizzle up front. This will be plugged
1017 * into either the sampler (for 16-bit returns) or the shader's
1018 * texture key (for 32)
1019 */
1020 uint8_t view_swizzle[4] = {
1021 cso->swizzle_r,
1022 cso->swizzle_g,
1023 cso->swizzle_b,
1024 cso->swizzle_a
1025 };
1026 const uint8_t *fmt_swizzle =
1027 v3d_get_format_swizzle(&screen->devinfo, so->base.format);
1028 util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle);
1029
1030 pipe_reference_init(&so->base.reference, 1);
1031 so->base.texture = prsc;
1032 so->base.context = pctx;
1033
1034 if (rsc->separate_stencil &&
1035 cso->format == PIPE_FORMAT_X32_S8X24_UINT) {
1036 rsc = rsc->separate_stencil;
1037 prsc = &rsc->base;
1038 }
1039
1040 /* If we're sampling depth from depth/stencil, demote the format to
1041 * just depth. u_format will end up giving the answers for the
1042 * stencil channel, otherwise.
1043 */
1044 enum pipe_format sample_format = cso->format;
1045 if (sample_format == PIPE_FORMAT_S8_UINT_Z24_UNORM)
1046 sample_format = PIPE_FORMAT_X8Z24_UNORM;
1047
1048 const struct util_format_description *desc =
1049 util_format_description(sample_format);
1050
1051 if (util_format_is_pure_integer(sample_format) &&
1052 !util_format_has_depth(desc)) {
1053 int chan = util_format_get_first_non_void_channel(sample_format);
1054 if (util_format_is_pure_uint(sample_format)) {
1055 switch (desc->channel[chan].size) {
1056 case 32:
1057 so->sampler_variant = V3D_SAMPLER_STATE_32;
1058 break;
1059 case 16:
1060 so->sampler_variant = V3D_SAMPLER_STATE_16U;
1061 break;
1062 case 10:
1063 so->sampler_variant = V3D_SAMPLER_STATE_1010102U;
1064 break;
1065 case 8:
1066 so->sampler_variant = V3D_SAMPLER_STATE_8U;
1067 break;
1068 }
1069 } else {
1070 switch (desc->channel[chan].size) {
1071 case 32:
1072 so->sampler_variant = V3D_SAMPLER_STATE_32;
1073 break;
1074 case 16:
1075 so->sampler_variant = V3D_SAMPLER_STATE_16I;
1076 break;
1077 case 8:
1078 so->sampler_variant = V3D_SAMPLER_STATE_8I;
1079 break;
1080 }
1081 }
1082 } else {
1083 if (v3d_get_tex_return_size(&screen->devinfo, sample_format) == 32) {
1084 if (util_format_is_alpha(sample_format))
1085 so->sampler_variant = V3D_SAMPLER_STATE_32_A;
1086 else
1087 so->sampler_variant = V3D_SAMPLER_STATE_32;
1088 } else {
1089 if (util_format_is_luminance_alpha(sample_format))
1090 so->sampler_variant = V3D_SAMPLER_STATE_F16_LA;
1091 else if (util_format_is_alpha(sample_format))
1092 so->sampler_variant = V3D_SAMPLER_STATE_F16_A;
1093 else if (fmt_swizzle[0] == PIPE_SWIZZLE_Z)
1094 so->sampler_variant = V3D_SAMPLER_STATE_F16_BGRA;
1095 else
1096 so->sampler_variant = V3D_SAMPLER_STATE_F16;
1097
1098 }
1099
1100 if (util_format_is_unorm(sample_format)) {
1101 so->sampler_variant += (V3D_SAMPLER_STATE_F16_UNORM -
1102 V3D_SAMPLER_STATE_F16);
1103 } else if (util_format_is_snorm(sample_format)){
1104 so->sampler_variant += (V3D_SAMPLER_STATE_F16_SNORM -
1105 V3D_SAMPLER_STATE_F16);
1106 }
1107 }
1108
1109 /* V3D still doesn't support sampling from raster textures, so we will
1110 * have to copy to a temporary tiled texture.
1111 */
1112 if (!rsc->tiled && !(prsc->target == PIPE_TEXTURE_1D ||
1113 prsc->target == PIPE_TEXTURE_1D_ARRAY ||
1114 prsc->target == PIPE_BUFFER)) {
1115 struct v3d_resource *shadow_parent = rsc;
1116 struct pipe_resource tmpl = {
1117 .target = prsc->target,
1118 .format = prsc->format,
1119 .width0 = u_minify(prsc->width0,
1120 cso->u.tex.first_level),
1121 .height0 = u_minify(prsc->height0,
1122 cso->u.tex.first_level),
1123 .depth0 = 1,
1124 .array_size = 1,
1125 .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
1126 .last_level = cso->u.tex.last_level - cso->u.tex.first_level,
1127 .nr_samples = prsc->nr_samples,
1128 };
1129
1130 /* Create the shadow texture. The rest of the sampler view
1131 * setup will use the shadow.
1132 */
1133 prsc = v3d_resource_create(pctx->screen, &tmpl);
1134 if (!prsc) {
1135 free(so);
1136 return NULL;
1137 }
1138 rsc = v3d_resource(prsc);
1139
1140 /* Flag it as needing update of the contents from the parent. */
1141 rsc->writes = shadow_parent->writes - 1;
1142 assert(rsc->tiled);
1143
1144 so->texture = prsc;
1145 } else {
1146 pipe_resource_reference(&so->texture, prsc);
1147 }
1148
1149 v3dX(create_texture_shader_state_bo)(v3d, so);
1150
1151 return &so->base;
1152 }
1153
1154 static void
v3d_sampler_view_destroy(struct pipe_context * pctx,struct pipe_sampler_view * psview)1155 v3d_sampler_view_destroy(struct pipe_context *pctx,
1156 struct pipe_sampler_view *psview)
1157 {
1158 struct v3d_sampler_view *sview = v3d_sampler_view(psview);
1159
1160 v3d_bo_unreference(&sview->bo);
1161 pipe_resource_reference(&psview->texture, NULL);
1162 pipe_resource_reference(&sview->texture, NULL);
1163 free(psview);
1164 }
1165
1166 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)1167 v3d_set_sampler_views(struct pipe_context *pctx,
1168 enum pipe_shader_type shader,
1169 unsigned start, unsigned nr,
1170 unsigned unbind_num_trailing_slots,
1171 bool take_ownership,
1172 struct pipe_sampler_view **views)
1173 {
1174 struct v3d_context *v3d = v3d_context(pctx);
1175 struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader];
1176 unsigned i;
1177 unsigned new_nr = 0;
1178
1179 assert(start == 0);
1180
1181 for (i = 0; i < nr; i++) {
1182 if (views[i])
1183 new_nr = i + 1;
1184 if (take_ownership) {
1185 pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
1186 stage_tex->textures[i] = views[i];
1187 } else {
1188 pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
1189 }
1190 /* If our sampler serial doesn't match our texture serial it
1191 * means the texture has been updated with a new BO, in which
1192 * case we need to update the sampler state to point to the
1193 * new BO as well
1194 */
1195 if (stage_tex->textures[i]) {
1196 struct v3d_sampler_view *so =
1197 v3d_sampler_view(stage_tex->textures[i]);
1198 struct v3d_resource *rsc = v3d_resource(so->texture);
1199 if (so->serial_id != rsc->serial_id)
1200 v3dX(create_texture_shader_state_bo)(v3d, so);
1201 }
1202 }
1203
1204 for (; i < stage_tex->num_textures; i++) {
1205 pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
1206 }
1207
1208 stage_tex->num_textures = new_nr;
1209
1210 v3d_flag_dirty_sampler_state(v3d, shader);
1211 }
1212
1213 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)1214 v3d_create_stream_output_target(struct pipe_context *pctx,
1215 struct pipe_resource *prsc,
1216 unsigned buffer_offset,
1217 unsigned buffer_size)
1218 {
1219 struct v3d_stream_output_target *target;
1220
1221 target = CALLOC_STRUCT(v3d_stream_output_target);
1222 if (!target)
1223 return NULL;
1224
1225 pipe_reference_init(&target->base.reference, 1);
1226 pipe_resource_reference(&target->base.buffer, prsc);
1227
1228 target->base.context = pctx;
1229 target->base.buffer_offset = buffer_offset;
1230 target->base.buffer_size = buffer_size;
1231
1232 return &target->base;
1233 }
1234
1235 static void
v3d_stream_output_target_destroy(struct pipe_context * pctx,struct pipe_stream_output_target * target)1236 v3d_stream_output_target_destroy(struct pipe_context *pctx,
1237 struct pipe_stream_output_target *target)
1238 {
1239 pipe_resource_reference(&target->buffer, NULL);
1240 free(target);
1241 }
1242
1243 static void
v3d_set_stream_output_targets(struct pipe_context * pctx,unsigned num_targets,struct pipe_stream_output_target ** targets,const unsigned * offsets)1244 v3d_set_stream_output_targets(struct pipe_context *pctx,
1245 unsigned num_targets,
1246 struct pipe_stream_output_target **targets,
1247 const unsigned *offsets)
1248 {
1249 struct v3d_context *ctx = v3d_context(pctx);
1250 struct v3d_streamout_stateobj *so = &ctx->streamout;
1251 unsigned i;
1252
1253 assert(num_targets <= ARRAY_SIZE(so->targets));
1254
1255 /* Update recorded vertex counts when we are ending the recording of
1256 * transform feedback. We do this when we switch primitive types
1257 * at draw time, but if we haven't switched primitives in our last
1258 * draw we need to do it here as well.
1259 */
1260 if (num_targets == 0 && so->num_targets > 0)
1261 v3d_update_primitive_counters(ctx);
1262
1263 /* If offset is (unsigned) -1, it means continue appending to the
1264 * buffer at the existing offset.
1265 */
1266 for (i = 0; i < num_targets; i++) {
1267 if (offsets[i] != (unsigned)-1)
1268 v3d_stream_output_target(targets[i])->offset = offsets[i];
1269
1270 pipe_so_target_reference(&so->targets[i], targets[i]);
1271 }
1272
1273 for (; i < so->num_targets; i++)
1274 pipe_so_target_reference(&so->targets[i], NULL);
1275
1276 so->num_targets = num_targets;
1277
1278 /* Create primitive counters BO if needed */
1279 if (num_targets > 0)
1280 v3d_ensure_prim_counts_allocated(ctx);
1281
1282 ctx->dirty |= V3D_DIRTY_STREAMOUT;
1283 }
1284
1285 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)1286 v3d_set_shader_buffers(struct pipe_context *pctx,
1287 enum pipe_shader_type shader,
1288 unsigned start, unsigned count,
1289 const struct pipe_shader_buffer *buffers,
1290 unsigned writable_bitmask)
1291 {
1292 struct v3d_context *v3d = v3d_context(pctx);
1293 struct v3d_ssbo_stateobj *so = &v3d->ssbo[shader];
1294
1295 if (buffers) {
1296 for (unsigned i = 0; i < count; i++) {
1297 unsigned n = i + start;
1298 struct pipe_shader_buffer *buf = &so->sb[n];
1299
1300 if ((buf->buffer == buffers[i].buffer) &&
1301 (buf->buffer_offset == buffers[i].buffer_offset) &&
1302 (buf->buffer_size == buffers[i].buffer_size))
1303 continue;
1304
1305 buf->buffer_offset = buffers[i].buffer_offset;
1306 buf->buffer_size = buffers[i].buffer_size;
1307 pipe_resource_reference(&buf->buffer, buffers[i].buffer);
1308
1309 if (buf->buffer)
1310 BITSET_SET(so->enabled_mask, n);
1311 else
1312 BITSET_CLEAR(so->enabled_mask, n);
1313 }
1314 } else {
1315 for (unsigned i = 0; i < count; i++) {
1316 unsigned n = i + start;
1317 struct pipe_shader_buffer *buf = &so->sb[n];
1318
1319 pipe_resource_reference(&buf->buffer, NULL);
1320 }
1321
1322 BITSET_CLEAR_RANGE(so->enabled_mask, start, start + count);
1323 }
1324
1325 v3d->dirty |= V3D_DIRTY_SSBO;
1326 }
1327
1328 static void
v3d_create_image_view_texture_shader_state(struct v3d_context * v3d,struct v3d_shaderimg_stateobj * so,int img)1329 v3d_create_image_view_texture_shader_state(struct v3d_context *v3d,
1330 struct v3d_shaderimg_stateobj *so,
1331 int img)
1332 {
1333 struct v3d_image_view *iview = &so->si[img];
1334
1335 void *map;
1336 u_upload_alloc(v3d->uploader, 0, cl_packet_length(TEXTURE_SHADER_STATE),
1337 32,
1338 &iview->tex_state_offset,
1339 &iview->tex_state,
1340 &map);
1341
1342 struct pipe_resource *prsc = iview->base.resource;
1343
1344 v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
1345 if (prsc->target != PIPE_BUFFER) {
1346 v3d_setup_texture_shader_state(&v3d->screen->devinfo,
1347 &tex, prsc,
1348 iview->base.u.tex.level,
1349 iview->base.u.tex.level,
1350 iview->base.u.tex.first_layer,
1351 iview->base.u.tex.last_layer,
1352 false);
1353 } else {
1354 v3d_setup_texture_shader_state_from_buffer(&tex, prsc,
1355 iview->base.format,
1356 iview->base.u.buf.offset,
1357 iview->base.u.buf.size);
1358 }
1359
1360 tex.swizzle_r = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_X);
1361 tex.swizzle_g = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_Y);
1362 tex.swizzle_b = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_Z);
1363 tex.swizzle_a = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_W);
1364
1365 tex.texture_type = v3d_get_tex_format(&v3d->screen->devinfo,
1366 iview->base.format);
1367 };
1368 }
1369
1370 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)1371 v3d_set_shader_images(struct pipe_context *pctx,
1372 enum pipe_shader_type shader,
1373 unsigned start, unsigned count,
1374 unsigned unbind_num_trailing_slots,
1375 const struct pipe_image_view *images)
1376 {
1377 struct v3d_context *v3d = v3d_context(pctx);
1378 struct v3d_shaderimg_stateobj *so = &v3d->shaderimg[shader];
1379
1380 if (images) {
1381 for (unsigned i = 0; i < count; i++) {
1382 unsigned n = i + start;
1383 struct v3d_image_view *iview = &so->si[n];
1384
1385 if ((iview->base.resource == images[i].resource) &&
1386 (iview->base.format == images[i].format) &&
1387 (iview->base.access == images[i].access) &&
1388 !memcmp(&iview->base.u, &images[i].u,
1389 sizeof(iview->base.u)))
1390 continue;
1391
1392 util_copy_image_view(&iview->base, &images[i]);
1393
1394 if (iview->base.resource) {
1395 BITSET_SET(so->enabled_mask, n);
1396 v3d_create_image_view_texture_shader_state(v3d,
1397 so,
1398 n);
1399 } else {
1400 BITSET_CLEAR(so->enabled_mask, n);
1401 pipe_resource_reference(&iview->tex_state, NULL);
1402 }
1403 }
1404 } else {
1405 for (unsigned i = 0; i < count; i++) {
1406 unsigned n = i + start;
1407 struct v3d_image_view *iview = &so->si[n];
1408
1409 pipe_resource_reference(&iview->base.resource, NULL);
1410 pipe_resource_reference(&iview->tex_state, NULL);
1411 }
1412
1413 BITSET_CLEAR_RANGE(so->enabled_mask, start, start + count);
1414 }
1415
1416 v3d->dirty |= V3D_DIRTY_SHADER_IMAGE;
1417
1418 if (unbind_num_trailing_slots) {
1419 v3d_set_shader_images(pctx, shader, start + count,
1420 unbind_num_trailing_slots, 0, NULL);
1421 }
1422 }
1423
1424 void
v3dX(state_init)1425 v3dX(state_init)(struct pipe_context *pctx)
1426 {
1427 pctx->set_blend_color = v3d_set_blend_color;
1428 pctx->set_stencil_ref = v3d_set_stencil_ref;
1429 pctx->set_clip_state = v3d_set_clip_state;
1430 pctx->set_sample_mask = v3d_set_sample_mask;
1431 pctx->set_constant_buffer = v3d_set_constant_buffer;
1432 pctx->set_framebuffer_state = v3d_set_framebuffer_state;
1433 pctx->set_polygon_stipple = v3d_set_polygon_stipple;
1434 pctx->set_scissor_states = v3d_set_scissor_states;
1435 pctx->set_viewport_states = v3d_set_viewport_states;
1436
1437 pctx->set_vertex_buffers = v3d_set_vertex_buffers;
1438
1439 pctx->create_blend_state = v3d_create_blend_state;
1440 pctx->bind_blend_state = v3d_blend_state_bind;
1441 pctx->delete_blend_state = v3d_generic_cso_state_delete;
1442
1443 pctx->create_rasterizer_state = v3d_create_rasterizer_state;
1444 pctx->bind_rasterizer_state = v3d_rasterizer_state_bind;
1445 pctx->delete_rasterizer_state = v3d_generic_cso_state_delete;
1446
1447 pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state;
1448 pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind;
1449 pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete;
1450
1451 pctx->create_vertex_elements_state = v3d_vertex_state_create;
1452 pctx->delete_vertex_elements_state = v3d_vertex_state_delete;
1453 pctx->bind_vertex_elements_state = v3d_vertex_state_bind;
1454
1455 pctx->create_sampler_state = v3d_create_sampler_state;
1456 pctx->delete_sampler_state = v3d_sampler_state_delete;
1457 pctx->bind_sampler_states = v3d_sampler_states_bind;
1458
1459 pctx->create_sampler_view = v3d_create_sampler_view;
1460 pctx->sampler_view_destroy = v3d_sampler_view_destroy;
1461 pctx->set_sampler_views = v3d_set_sampler_views;
1462
1463 pctx->set_shader_buffers = v3d_set_shader_buffers;
1464 pctx->set_shader_images = v3d_set_shader_images;
1465
1466 pctx->create_stream_output_target = v3d_create_stream_output_target;
1467 pctx->stream_output_target_destroy = v3d_stream_output_target_destroy;
1468 pctx->set_stream_output_targets = v3d_set_stream_output_targets;
1469 }
1470