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