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