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