xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/freedreno/a6xx/fd6_texture.cc (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2016 Rob Clark <[email protected]>
3  * Copyright © 2018 Google, Inc.
4  * SPDX-License-Identifier: MIT
5  *
6  * Authors:
7  *    Rob Clark <[email protected]>
8  */
9 
10 #define FD_BO_NO_HARDPIN 1
11 
12 #include "pipe/p_state.h"
13 #include "util/format/u_format.h"
14 #include "util/hash_table.h"
15 #include "util/u_inlines.h"
16 #include "util/u_memory.h"
17 #include "util/u_string.h"
18 
19 #include "freedreno_dev_info.h"
20 #include "fd6_emit.h"
21 #include "fd6_resource.h"
22 #include "fd6_screen.h"
23 #include "fd6_texture.h"
24 
25 static void fd6_texture_state_destroy(struct fd6_texture_state *state);
26 
27 static void
remove_tex_entry(struct fd6_context * fd6_ctx,struct hash_entry * entry)28 remove_tex_entry(struct fd6_context *fd6_ctx, struct hash_entry *entry)
29 {
30    struct fd6_texture_state *tex = (struct fd6_texture_state *)entry->data;
31    _mesa_hash_table_remove(fd6_ctx->tex_cache, entry);
32    fd6_texture_state_destroy(tex);
33 }
34 
35 static enum a6xx_tex_clamp
tex_clamp(unsigned wrap,bool * needs_border)36 tex_clamp(unsigned wrap, bool *needs_border)
37 {
38    switch (wrap) {
39    case PIPE_TEX_WRAP_REPEAT:
40       return A6XX_TEX_REPEAT;
41    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
42       return A6XX_TEX_CLAMP_TO_EDGE;
43    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
44       *needs_border = true;
45       return A6XX_TEX_CLAMP_TO_BORDER;
46    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
47       /* only works for PoT.. need to emulate otherwise! */
48       return A6XX_TEX_MIRROR_CLAMP;
49    case PIPE_TEX_WRAP_MIRROR_REPEAT:
50       return A6XX_TEX_MIRROR_REPEAT;
51    case PIPE_TEX_WRAP_MIRROR_CLAMP:
52    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
53       /* these two we could perhaps emulate, but we currently
54        * just don't advertise PIPE_CAP_TEXTURE_MIRROR_CLAMP
55        */
56    default:
57       DBG("invalid wrap: %u", wrap);
58       return (enum a6xx_tex_clamp)0;
59    }
60 }
61 
62 static enum a6xx_tex_filter
tex_filter(unsigned filter,bool aniso)63 tex_filter(unsigned filter, bool aniso)
64 {
65    switch (filter) {
66    case PIPE_TEX_FILTER_NEAREST:
67       return A6XX_TEX_NEAREST;
68    case PIPE_TEX_FILTER_LINEAR:
69       return aniso ? A6XX_TEX_ANISO : A6XX_TEX_LINEAR;
70    default:
71       DBG("invalid filter: %u", filter);
72       return (enum a6xx_tex_filter)0;
73    }
74 }
75 
76 static enum a6xx_reduction_mode
reduction_mode(unsigned reduction_mode)77 reduction_mode(unsigned reduction_mode)
78 {
79    switch (reduction_mode) {
80    default:
81    case PIPE_TEX_REDUCTION_WEIGHTED_AVERAGE:
82       return A6XX_REDUCTION_MODE_AVERAGE;
83    case PIPE_TEX_REDUCTION_MIN:
84       return A6XX_REDUCTION_MODE_MIN;
85    case PIPE_TEX_REDUCTION_MAX:
86       return A6XX_REDUCTION_MODE_MAX;
87    }
88 }
89 
90 static void
setup_border_color(struct fd_screen * screen,const struct pipe_sampler_state * sampler,struct fd6_bcolor_entry * e)91 setup_border_color(struct fd_screen *screen,
92                    const struct pipe_sampler_state *sampler,
93                    struct fd6_bcolor_entry *e)
94 {
95    STATIC_ASSERT(sizeof(struct fd6_bcolor_entry) == FD6_BORDER_COLOR_SIZE);
96    const bool has_z24uint_s8uint = screen->info->a6xx.has_z24uint_s8uint;
97    const union pipe_color_union *bc = &sampler->border_color;
98 
99    enum pipe_format format = sampler->border_color_format;
100    const struct util_format_description *desc =
101       util_format_description(format);
102 
103    e->rgb565 = 0;
104    e->rgb5a1 = 0;
105    e->rgba4 = 0;
106    e->rgb10a2 = 0;
107    e->z24 = 0;
108 
109    unsigned char swiz[4];
110 
111    fdl6_format_swiz(format, false, swiz);
112 
113    for (unsigned j = 0; j < 4; j++) {
114       int c = swiz[j];
115       int cd = c;
116 
117       /*
118        * HACK: for PIPE_FORMAT_X24S8_UINT we end up w/ the
119        * stencil border color value in bc->ui[0] but according
120        * to desc->swizzle and desc->channel, the .x/.w component
121        * is NONE and the stencil value is in the y component.
122        * Meanwhile the hardware wants this in the .x component
123        * for x24s8 and x32_s8x24, or the .y component for x24s8 with the
124        * special Z24UINT_S8UINT format.
125        */
126       if ((format == PIPE_FORMAT_X24S8_UINT) ||
127           (format == PIPE_FORMAT_X32_S8X24_UINT)) {
128          if (j == 0) {
129             c = 1;
130             cd = (format == PIPE_FORMAT_X24S8_UINT && has_z24uint_s8uint) ? 1 : 0;
131          } else {
132             continue;
133          }
134       }
135 
136       if (c >= 4)
137          continue;
138 
139       if (desc->channel[c].pure_integer) {
140          uint16_t clamped;
141          switch (desc->channel[c].size) {
142          case 2:
143             assert(desc->channel[c].type == UTIL_FORMAT_TYPE_UNSIGNED);
144             clamped = CLAMP(bc->ui[j], 0, 0x3);
145             break;
146          case 8:
147             if (desc->channel[c].type == UTIL_FORMAT_TYPE_SIGNED)
148                clamped = CLAMP(bc->i[j], -128, 127);
149             else
150                clamped = CLAMP(bc->ui[j], 0, 255);
151             break;
152          case 10:
153             assert(desc->channel[c].type == UTIL_FORMAT_TYPE_UNSIGNED);
154             clamped = CLAMP(bc->ui[j], 0, 0x3ff);
155             break;
156          case 16:
157             if (desc->channel[c].type == UTIL_FORMAT_TYPE_SIGNED)
158                clamped = CLAMP(bc->i[j], -32768, 32767);
159             else
160                clamped = CLAMP(bc->ui[j], 0, 65535);
161             break;
162          default:
163             unreachable("Unexpected bit size");
164          case 32:
165             clamped = 0;
166             break;
167          }
168          e->fp32[cd] = bc->ui[j];
169          e->fp16[cd] = clamped;
170       } else {
171          float f = bc->f[j];
172          float f_u = CLAMP(f, 0, 1);
173          float f_s = CLAMP(f, -1, 1);
174 
175          e->fp32[c] = fui(f);
176          e->fp16[c] = _mesa_float_to_half(f);
177          e->srgb[c] = _mesa_float_to_half(f_u);
178          e->ui16[c] = f_u * 0xffff;
179          e->si16[c] = f_s * 0x7fff;
180          e->ui8[c] = f_u * 0xff;
181          e->si8[c] = f_s * 0x7f;
182 
183          if (c == 1)
184             e->rgb565 |= (int)(f_u * 0x3f) << 5;
185          else if (c < 3)
186             e->rgb565 |= (int)(f_u * 0x1f) << (c ? 11 : 0);
187          if (c == 3)
188             e->rgb5a1 |= (f_u > 0.5f) ? 0x8000 : 0;
189          else
190             e->rgb5a1 |= (int)(f_u * 0x1f) << (c * 5);
191          if (c == 3)
192             e->rgb10a2 |= (int)(f_u * 0x3) << 30;
193          else
194             e->rgb10a2 |= (int)(f_u * 0x3ff) << (c * 10);
195          e->rgba4 |= (int)(f_u * 0xf) << (c * 4);
196          if (c == 0)
197             e->z24 = f_u * 0xffffff;
198       }
199    }
200 }
201 
202 static uint32_t
bcolor_key_hash(const void * _key)203 bcolor_key_hash(const void *_key)
204 {
205    const struct fd6_bcolor_entry *key = (const struct fd6_bcolor_entry *)_key;
206    return XXH32(key, sizeof(*key), 0);
207 }
208 
209 static bool
bcolor_key_equals(const void * _a,const void * _b)210 bcolor_key_equals(const void *_a, const void *_b)
211 {
212    const struct fd6_bcolor_entry *a = (const struct fd6_bcolor_entry *)_a;
213    const struct fd6_bcolor_entry *b = (const struct fd6_bcolor_entry *)_b;
214    return memcmp(a, b, sizeof(struct fd6_bcolor_entry)) == 0;
215 }
216 
217 static unsigned
get_bcolor_offset(struct fd_context * ctx,const struct pipe_sampler_state * sampler)218 get_bcolor_offset(struct fd_context *ctx, const struct pipe_sampler_state *sampler)
219 {
220    struct fd6_context *fd6_ctx = fd6_context(ctx);
221    struct fd6_bcolor_entry *entries =
222          (struct fd6_bcolor_entry *)fd_bo_map(fd6_ctx->bcolor_mem);
223    struct fd6_bcolor_entry key = {};
224 
225    setup_border_color(ctx->screen, sampler, &key);
226 
227    uint32_t hash = bcolor_key_hash(&key);
228 
229    struct hash_entry *entry =
230       _mesa_hash_table_search_pre_hashed(fd6_ctx->bcolor_cache, hash, &key);
231 
232    if (entry) {
233       return (unsigned)(uintptr_t)entry->data;
234    }
235 
236    unsigned idx = fd6_ctx->bcolor_cache->entries;
237    if (idx >= FD6_MAX_BORDER_COLORS) {
238       mesa_loge("too many border colors");
239       return 0;
240    }
241 
242    entries[idx] = key;
243 
244    _mesa_hash_table_insert_pre_hashed(fd6_ctx->bcolor_cache, hash,
245                                       &entries[idx], (void *)(uintptr_t)idx);
246 
247    return idx;
248 }
249 
250 static void *
fd6_sampler_state_create(struct pipe_context * pctx,const struct pipe_sampler_state * cso)251 fd6_sampler_state_create(struct pipe_context *pctx,
252                          const struct pipe_sampler_state *cso)
253 {
254    struct fd6_sampler_stateobj *so = CALLOC_STRUCT(fd6_sampler_stateobj);
255    struct fd_context *ctx = fd_context(pctx);
256    unsigned aniso = util_last_bit(MIN2(cso->max_anisotropy >> 1, 8));
257    bool miplinear = false;
258 
259    if (!so)
260       return NULL;
261 
262    so->base = *cso;
263    so->seqno = util_idalloc_alloc(&fd6_context(ctx)->tex_ids);
264 
265    if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
266       miplinear = true;
267 
268    bool needs_border = false;
269    so->texsamp0 =
270       COND(miplinear, A6XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR) |
271       A6XX_TEX_SAMP_0_XY_MAG(tex_filter(cso->mag_img_filter, aniso)) |
272       A6XX_TEX_SAMP_0_XY_MIN(tex_filter(cso->min_img_filter, aniso)) |
273       A6XX_TEX_SAMP_0_ANISO((enum a6xx_tex_aniso)aniso) |
274       A6XX_TEX_SAMP_0_WRAP_S(tex_clamp(cso->wrap_s, &needs_border)) |
275       A6XX_TEX_SAMP_0_WRAP_T(tex_clamp(cso->wrap_t, &needs_border)) |
276       A6XX_TEX_SAMP_0_WRAP_R(tex_clamp(cso->wrap_r, &needs_border));
277 
278    so->texsamp1 =
279       COND(cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE,
280            A6XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR) |
281       COND(!cso->seamless_cube_map, A6XX_TEX_SAMP_1_CUBEMAPSEAMLESSFILTOFF) |
282       COND(cso->unnormalized_coords, A6XX_TEX_SAMP_1_UNNORM_COORDS);
283 
284    so->texsamp0 |= A6XX_TEX_SAMP_0_LOD_BIAS(cso->lod_bias);
285    so->texsamp1 |= A6XX_TEX_SAMP_1_MIN_LOD(cso->min_lod) |
286                    A6XX_TEX_SAMP_1_MAX_LOD(cso->max_lod);
287 
288    if (cso->compare_mode)
289       so->texsamp1 |=
290          A6XX_TEX_SAMP_1_COMPARE_FUNC((enum adreno_compare_func)cso->compare_func); /* maps 1:1 */
291 
292    if (needs_border)
293       so->texsamp2 = A6XX_TEX_SAMP_2_BCOLOR(get_bcolor_offset(ctx, cso));
294 
295    /* We don't know if the format is going to be YUV.  Setting CHROMA_LINEAR
296     * unconditionally seems fine.
297     */
298    if (cso->mag_img_filter == PIPE_TEX_FILTER_LINEAR &&
299        cso->min_img_filter == PIPE_TEX_FILTER_LINEAR)
300       so->texsamp2 |= A6XX_TEX_SAMP_2_CHROMA_LINEAR;
301 
302    so->texsamp2 |=
303       A6XX_TEX_SAMP_2_REDUCTION_MODE(reduction_mode(cso->reduction_mode));
304 
305    return so;
306 }
307 
308 static void
fd6_sampler_state_delete(struct pipe_context * pctx,void * hwcso)309 fd6_sampler_state_delete(struct pipe_context *pctx, void *hwcso)
310 {
311    struct fd_context *ctx = fd_context(pctx);
312    struct fd6_context *fd6_ctx = fd6_context(ctx);
313    struct fd6_sampler_stateobj *samp = (struct fd6_sampler_stateobj *)hwcso;
314 
315    fd_screen_lock(ctx->screen);
316 
317    hash_table_foreach (fd6_ctx->tex_cache, entry) {
318       struct fd6_texture_state *state = (struct fd6_texture_state *)entry->data;
319 
320       for (unsigned i = 0; i < ARRAY_SIZE(state->key.samp_seqno); i++) {
321          if (samp->seqno == state->key.samp_seqno[i]) {
322             remove_tex_entry(fd6_ctx, entry);
323             break;
324          }
325       }
326    }
327 
328    fd_screen_unlock(ctx->screen);
329 
330    util_idalloc_free(&fd6_ctx->tex_ids, samp->seqno);
331 
332    free(hwcso);
333 }
334 
335 static struct pipe_sampler_view *
fd6_sampler_view_create(struct pipe_context * pctx,struct pipe_resource * prsc,const struct pipe_sampler_view * cso)336 fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
337                         const struct pipe_sampler_view *cso)
338 {
339    struct fd6_context *fd6_ctx = fd6_context(fd_context(pctx));
340    struct fd6_pipe_sampler_view *so = CALLOC_STRUCT(fd6_pipe_sampler_view);
341 
342    if (!so)
343       return NULL;
344 
345    so->base = *cso;
346    so->seqno = util_idalloc_alloc(&fd6_ctx->tex_ids);
347    pipe_reference(NULL, &prsc->reference);
348    so->base.texture = prsc;
349    so->base.reference.count = 1;
350    so->base.context = pctx;
351 
352    return &so->base;
353 }
354 
355 /**
356  * Remove any texture state entries that reference the specified sampler
357  * view.
358  */
359 static void
fd6_sampler_view_invalidate(struct fd_context * ctx,struct fd6_pipe_sampler_view * view)360 fd6_sampler_view_invalidate(struct fd_context *ctx,
361                             struct fd6_pipe_sampler_view *view)
362 {
363    struct fd6_context *fd6_ctx = fd6_context(ctx);
364 
365    fd_screen_lock(ctx->screen);
366 
367    hash_table_foreach (fd6_ctx->tex_cache, entry) {
368       struct fd6_texture_state *state = (struct fd6_texture_state *)entry->data;
369 
370       for (unsigned i = 0; i < ARRAY_SIZE(state->key.view_seqno); i++) {
371          if (view->seqno == state->key.view_seqno[i]) {
372             remove_tex_entry(fd6_ctx, entry);
373             break;
374          }
375       }
376    }
377 
378    fd_screen_unlock(ctx->screen);
379 }
380 
381 static void
fd6_sampler_view_update(struct fd_context * ctx,struct fd6_pipe_sampler_view * so)382 fd6_sampler_view_update(struct fd_context *ctx,
383                         struct fd6_pipe_sampler_view *so)
384    assert_dt
385 {
386    const struct pipe_sampler_view *cso = &so->base;
387    struct pipe_resource *prsc = cso->texture;
388    struct fd_resource *rsc = fd_resource(prsc);
389    enum pipe_format format = cso->format;
390 
391    fd6_assert_valid_format(rsc, cso->format);
392 
393    /* If texture has not had a layout change, then no update needed: */
394    if (so->rsc_seqno == rsc->seqno)
395       return;
396 
397    fd6_sampler_view_invalidate(ctx, so);
398 
399    so->rsc_seqno = rsc->seqno;
400 
401    if (format == PIPE_FORMAT_X32_S8X24_UINT) {
402       rsc = rsc->stencil;
403       format = rsc->b.b.format;
404    }
405 
406    so->ptr1 = rsc;
407 
408    if (cso->target == PIPE_BUFFER) {
409       uint8_t swiz[4] = {cso->swizzle_r, cso->swizzle_g, cso->swizzle_b,
410                          cso->swizzle_a};
411 
412       /* Using relocs for addresses still */
413       uint64_t iova = cso->u.buf.offset;
414 
415       uint32_t size = fd_clamp_buffer_size(cso->format, cso->u.buf.size,
416                                            A4XX_MAX_TEXEL_BUFFER_ELEMENTS_UINT);
417 
418       fdl6_buffer_view_init(so->descriptor, cso->format, swiz, iova, size);
419    } else {
420       struct fdl_view_args args = {
421          .chip = ctx->screen->gen,
422 
423          /* Using relocs for addresses still */
424          .iova = 0,
425 
426          .base_miplevel = fd_sampler_first_level(cso),
427          .level_count =
428             fd_sampler_last_level(cso) - fd_sampler_first_level(cso) + 1,
429 
430          .base_array_layer = cso->u.tex.first_layer,
431          .layer_count = cso->u.tex.last_layer - cso->u.tex.first_layer + 1,
432 
433          .swiz = {cso->swizzle_r, cso->swizzle_g, cso->swizzle_b,
434                   cso->swizzle_a},
435          .format = format,
436 
437          .type = fdl_type_from_pipe_target(cso->target),
438          .chroma_offsets = {FDL_CHROMA_LOCATION_COSITED_EVEN,
439                             FDL_CHROMA_LOCATION_COSITED_EVEN},
440          .ubwc_fc_mutable = false,
441       };
442 
443       if (rsc->b.b.format == PIPE_FORMAT_R8_G8B8_420_UNORM) {
444          args.chroma_offsets[0] = FDL_CHROMA_LOCATION_MIDPOINT;
445          args.chroma_offsets[1] = FDL_CHROMA_LOCATION_MIDPOINT;
446       }
447 
448       struct fd_resource *plane1 = fd_resource(rsc->b.b.next);
449       struct fd_resource *plane2 =
450          plane1 ? fd_resource(plane1->b.b.next) : NULL;
451       static const struct fdl_layout dummy_layout = {};
452       const struct fdl_layout *layouts[3] = {
453          &rsc->layout,
454          plane1 ? &plane1->layout : &dummy_layout,
455          plane2 ? &plane2->layout : &dummy_layout,
456       };
457       struct fdl6_view view;
458       fdl6_view_init(&view, layouts, &args,
459                      ctx->screen->info->a6xx.has_z24uint_s8uint);
460       memcpy(so->descriptor, view.descriptor, sizeof(so->descriptor));
461 
462       if (rsc->b.b.format == PIPE_FORMAT_R8_G8B8_420_UNORM) {
463          /* In case of biplanar R8_G8B8, the UBWC metadata address in
464           * dwords 7 and 8, is instead the pointer to the second plane.
465           */
466          so->ptr2 = plane1;
467       } else {
468          if (fd_resource_ubwc_enabled(rsc, fd_sampler_first_level(cso))) {
469             so->ptr2 = rsc;
470          }
471       }
472    }
473 }
474 
475 static void
fd6_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)476 fd6_set_sampler_views(struct pipe_context *pctx, enum pipe_shader_type shader,
477                       unsigned start, unsigned nr,
478                       unsigned unbind_num_trailing_slots,
479                       bool take_ownership,
480                       struct pipe_sampler_view **views)
481    in_dt
482 {
483    struct fd_context *ctx = fd_context(pctx);
484 
485    fd_set_sampler_views(pctx, shader, start, nr, unbind_num_trailing_slots,
486                         take_ownership, views);
487 
488    if (!views)
489       return;
490 
491    for (unsigned i = 0; i < nr; i++) {
492       struct fd6_pipe_sampler_view *so = fd6_pipe_sampler_view(views[i + start]);
493 
494       if (!so)
495          continue;
496 
497       struct fd_resource *rsc = fd_resource(so->base.texture);
498 
499       fd6_validate_format(ctx, rsc, so->base.format);
500       fd6_sampler_view_update(ctx, so);
501    }
502 }
503 
504 /* NOTE this can be called in either driver thread or frontend thread
505  * depending on where the last unref comes from
506  */
507 static void
fd6_sampler_view_destroy(struct pipe_context * pctx,struct pipe_sampler_view * _view)508 fd6_sampler_view_destroy(struct pipe_context *pctx,
509                          struct pipe_sampler_view *_view)
510 {
511    struct fd_context *ctx = fd_context(pctx);
512    struct fd6_pipe_sampler_view *view = fd6_pipe_sampler_view(_view);
513 
514    fd6_sampler_view_invalidate(ctx, view);
515 
516    pipe_resource_reference(&view->base.texture, NULL);
517 
518    util_idalloc_free(&fd6_context(ctx)->tex_ids, view->seqno);
519 
520    free(view);
521 }
522 
523 static uint32_t
tex_key_hash(const void * _key)524 tex_key_hash(const void *_key)
525 {
526    const struct fd6_texture_key *key = (const struct fd6_texture_key *)_key;
527    return XXH32(key, sizeof(*key), 0);
528 }
529 
530 static bool
tex_key_equals(const void * _a,const void * _b)531 tex_key_equals(const void *_a, const void *_b)
532 {
533    const struct fd6_texture_key *a = (const struct fd6_texture_key *)_a;
534    const struct fd6_texture_key *b = (const struct fd6_texture_key *)_b;
535    return memcmp(a, b, sizeof(struct fd6_texture_key)) == 0;
536 }
537 
538 static struct fd_ringbuffer *
build_texture_state(struct fd_context * ctx,enum pipe_shader_type type,struct fd_texture_stateobj * tex)539 build_texture_state(struct fd_context *ctx, enum pipe_shader_type type,
540                     struct fd_texture_stateobj *tex)
541    assert_dt
542 {
543    struct fd_ringbuffer *ring = fd_ringbuffer_new_object(ctx->pipe, 32 * 4);
544    unsigned opcode, tex_samp_reg, tex_const_reg, tex_count_reg;
545    enum a6xx_state_block sb;
546 
547    switch (type) {
548    case PIPE_SHADER_VERTEX:
549       sb = SB6_VS_TEX;
550       opcode = CP_LOAD_STATE6_GEOM;
551       tex_samp_reg = REG_A6XX_SP_VS_TEX_SAMP;
552       tex_const_reg = REG_A6XX_SP_VS_TEX_CONST;
553       tex_count_reg = REG_A6XX_SP_VS_TEX_COUNT;
554       break;
555    case PIPE_SHADER_TESS_CTRL:
556       sb = SB6_HS_TEX;
557       opcode = CP_LOAD_STATE6_GEOM;
558       tex_samp_reg = REG_A6XX_SP_HS_TEX_SAMP;
559       tex_const_reg = REG_A6XX_SP_HS_TEX_CONST;
560       tex_count_reg = REG_A6XX_SP_HS_TEX_COUNT;
561       break;
562    case PIPE_SHADER_TESS_EVAL:
563       sb = SB6_DS_TEX;
564       opcode = CP_LOAD_STATE6_GEOM;
565       tex_samp_reg = REG_A6XX_SP_DS_TEX_SAMP;
566       tex_const_reg = REG_A6XX_SP_DS_TEX_CONST;
567       tex_count_reg = REG_A6XX_SP_DS_TEX_COUNT;
568       break;
569    case PIPE_SHADER_GEOMETRY:
570       sb = SB6_GS_TEX;
571       opcode = CP_LOAD_STATE6_GEOM;
572       tex_samp_reg = REG_A6XX_SP_GS_TEX_SAMP;
573       tex_const_reg = REG_A6XX_SP_GS_TEX_CONST;
574       tex_count_reg = REG_A6XX_SP_GS_TEX_COUNT;
575       break;
576    case PIPE_SHADER_FRAGMENT:
577       sb = SB6_FS_TEX;
578       opcode = CP_LOAD_STATE6_FRAG;
579       tex_samp_reg = REG_A6XX_SP_FS_TEX_SAMP;
580       tex_const_reg = REG_A6XX_SP_FS_TEX_CONST;
581       tex_count_reg = REG_A6XX_SP_FS_TEX_COUNT;
582       break;
583    case PIPE_SHADER_COMPUTE:
584       sb = SB6_CS_TEX;
585       opcode = CP_LOAD_STATE6_FRAG;
586       tex_samp_reg = REG_A6XX_SP_CS_TEX_SAMP;
587       tex_const_reg = REG_A6XX_SP_CS_TEX_CONST;
588       tex_count_reg = REG_A6XX_SP_CS_TEX_COUNT;
589       break;
590    default:
591       unreachable("bad state block");
592    }
593 
594    if (tex->num_samplers > 0) {
595       struct fd_ringbuffer *state =
596          fd_ringbuffer_new_object(ctx->pipe, tex->num_samplers * 4 * 4);
597       for (unsigned i = 0; i < tex->num_samplers; i++) {
598          static const struct fd6_sampler_stateobj dummy_sampler = {};
599          const struct fd6_sampler_stateobj *sampler =
600             tex->samplers[i] ? fd6_sampler_stateobj(tex->samplers[i])
601                              : &dummy_sampler;
602          OUT_RING(state, sampler->texsamp0);
603          OUT_RING(state, sampler->texsamp1);
604          OUT_RING(state, sampler->texsamp2);
605          OUT_RING(state, sampler->texsamp3);
606       }
607 
608       /* output sampler state: */
609       OUT_PKT7(ring, opcode, 3);
610       OUT_RING(ring, CP_LOAD_STATE6_0_DST_OFF(0) |
611                         CP_LOAD_STATE6_0_STATE_TYPE(ST6_SHADER) |
612                         CP_LOAD_STATE6_0_STATE_SRC(SS6_INDIRECT) |
613                         CP_LOAD_STATE6_0_STATE_BLOCK(sb) |
614                         CP_LOAD_STATE6_0_NUM_UNIT(tex->num_samplers));
615       OUT_RB(ring, state); /* SRC_ADDR_LO/HI */
616 
617       OUT_PKT4(ring, tex_samp_reg, 2);
618       OUT_RB(ring, state); /* SRC_ADDR_LO/HI */
619 
620       fd_ringbuffer_del(state);
621    }
622 
623    unsigned num_textures = tex->num_textures;
624 
625    if (num_textures > 0) {
626       struct fd_ringbuffer *state =
627          fd_ringbuffer_new_object(ctx->pipe, num_textures * 16 * 4);
628       for (unsigned i = 0; i < num_textures; i++) {
629          const struct fd6_pipe_sampler_view *view;
630 
631          if (tex->textures[i]) {
632             view = fd6_pipe_sampler_view(tex->textures[i]);
633             struct fd_resource *rsc = fd_resource(view->base.texture);
634             fd6_assert_valid_format(rsc, view->base.format);
635             assert(view->rsc_seqno == rsc->seqno);
636          } else {
637             static const struct fd6_pipe_sampler_view dummy_view = {};
638             view = &dummy_view;
639          }
640 
641          OUT_RING(state, view->descriptor[0]);
642          OUT_RING(state, view->descriptor[1]);
643          OUT_RING(state, view->descriptor[2]);
644          OUT_RING(state, view->descriptor[3]);
645 
646          if (view->ptr1) {
647             OUT_RELOC(state, view->ptr1->bo, view->descriptor[4],
648                       (uint64_t)view->descriptor[5] << 32, 0);
649          } else {
650             OUT_RING(state, view->descriptor[4]);
651             OUT_RING(state, view->descriptor[5]);
652          }
653 
654          OUT_RING(state, view->descriptor[6]);
655 
656          if (view->ptr2) {
657             OUT_RELOC(state, view->ptr2->bo, view->descriptor[7], 0, 0);
658          } else {
659             OUT_RING(state, view->descriptor[7]);
660             OUT_RING(state, view->descriptor[8]);
661          }
662 
663          OUT_RING(state, view->descriptor[9]);
664          OUT_RING(state, view->descriptor[10]);
665          OUT_RING(state, view->descriptor[11]);
666          OUT_RING(state, view->descriptor[12]);
667          OUT_RING(state, view->descriptor[13]);
668          OUT_RING(state, view->descriptor[14]);
669          OUT_RING(state, view->descriptor[15]);
670       }
671 
672       /* emit texture state: */
673       OUT_PKT7(ring, opcode, 3);
674       OUT_RING(ring, CP_LOAD_STATE6_0_DST_OFF(0) |
675                         CP_LOAD_STATE6_0_STATE_TYPE(ST6_CONSTANTS) |
676                         CP_LOAD_STATE6_0_STATE_SRC(SS6_INDIRECT) |
677                         CP_LOAD_STATE6_0_STATE_BLOCK(sb) |
678                         CP_LOAD_STATE6_0_NUM_UNIT(num_textures));
679       OUT_RB(ring, state); /* SRC_ADDR_LO/HI */
680 
681       OUT_PKT4(ring, tex_const_reg, 2);
682       OUT_RB(ring, state); /* SRC_ADDR_LO/HI */
683 
684       fd_ringbuffer_del(state);
685    }
686 
687    OUT_PKT4(ring, tex_count_reg, 1);
688    OUT_RING(ring, num_textures);
689 
690    return ring;
691 }
692 
693 /**
694  * Handle invalidates potentially coming from other contexts.  By
695  * flagging the invalidate rather than handling it immediately, we
696  * avoid needing to refcnt (with it's associated atomics) the tex
697  * state.  And furthermore, this avoids cross-ctx (thread) sharing
698  * of fd_ringbuffer's, avoiding their need for atomic refcnts.
699  */
700 static void
handle_invalidates(struct fd_context * ctx)701 handle_invalidates(struct fd_context *ctx)
702    assert_dt
703 {
704    struct fd6_context *fd6_ctx = fd6_context(ctx);
705 
706    fd_screen_lock(ctx->screen);
707 
708    hash_table_foreach (fd6_ctx->tex_cache, entry) {
709       struct fd6_texture_state *state = (struct fd6_texture_state *)entry->data;
710 
711       if (state->invalidate)
712          remove_tex_entry(fd6_ctx, entry);
713    }
714 
715    fd_screen_unlock(ctx->screen);
716 
717    for (unsigned type = 0; type < ARRAY_SIZE(ctx->tex); type++) {
718       struct fd_texture_stateobj *tex = &ctx->tex[type];
719 
720       for (unsigned i = 0; i < tex->num_textures; i++) {
721          struct fd6_pipe_sampler_view *so =
722                fd6_pipe_sampler_view(tex->textures[i]);
723 
724          if (!so)
725             continue;
726 
727          fd6_sampler_view_update(ctx, so);
728       }
729    }
730 
731    fd6_ctx->tex_cache_needs_invalidate = false;
732 }
733 
734 struct fd6_texture_state *
fd6_texture_state(struct fd_context * ctx,enum pipe_shader_type type)735 fd6_texture_state(struct fd_context *ctx, enum pipe_shader_type type)
736 {
737    struct fd_texture_stateobj *tex = &ctx->tex[type];
738    struct fd6_context *fd6_ctx = fd6_context(ctx);
739    struct fd6_texture_state *state = NULL;
740    struct fd6_texture_key key;
741 
742    if (unlikely(fd6_ctx->tex_cache_needs_invalidate))
743       handle_invalidates(ctx);
744 
745    memset(&key, 0, sizeof(key));
746 
747    for (unsigned i = 0; i < tex->num_textures; i++) {
748       if (!tex->textures[i])
749          continue;
750 
751       struct fd6_pipe_sampler_view *view =
752          fd6_pipe_sampler_view(tex->textures[i]);
753 
754       key.view_seqno[i] = view->seqno;
755    }
756 
757    for (unsigned i = 0; i < tex->num_samplers; i++) {
758       if (!tex->samplers[i])
759          continue;
760 
761       struct fd6_sampler_stateobj *sampler =
762          fd6_sampler_stateobj(tex->samplers[i]);
763 
764       key.samp_seqno[i] = sampler->seqno;
765    }
766 
767    key.type = type;
768 
769    uint32_t hash = tex_key_hash(&key);
770    fd_screen_lock(ctx->screen);
771 
772    struct hash_entry *entry =
773       _mesa_hash_table_search_pre_hashed(fd6_ctx->tex_cache, hash, &key);
774 
775    if (entry) {
776       state = (struct fd6_texture_state *)entry->data;
777       for (unsigned i = 0; i < tex->num_textures; i++) {
778          uint16_t seqno = tex->textures[i] ?
779                fd_resource(tex->textures[i]->texture)->seqno : 0;
780 
781          assert(state->view_rsc_seqno[i] == seqno);
782       }
783       goto out_unlock;
784    }
785 
786    state = CALLOC_STRUCT(fd6_texture_state);
787 
788    for (unsigned i = 0; i < tex->num_textures; i++) {
789       if (!tex->textures[i])
790          continue;
791 
792       struct fd_resource *rsc = fd_resource(tex->textures[i]->texture);
793 
794       assert(rsc->dirty & FD_DIRTY_TEX);
795 
796       state->view_rsc_seqno[i] = rsc->seqno;
797    }
798 
799    state->key = key;
800    state->stateobj = build_texture_state(ctx, type, tex);
801 
802    /* NOTE: uses copy of key in state obj, because pointer passed by caller
803     * is probably on the stack
804     */
805    _mesa_hash_table_insert_pre_hashed(fd6_ctx->tex_cache, hash, &state->key,
806                                       state);
807 
808 out_unlock:
809    fd_screen_unlock(ctx->screen);
810    return state;
811 }
812 
813 static void
fd6_texture_state_destroy(struct fd6_texture_state * state)814 fd6_texture_state_destroy(struct fd6_texture_state *state)
815 {
816    fd_ringbuffer_del(state->stateobj);
817    free(state);
818 }
819 
820 static void
fd6_rebind_resource(struct fd_context * ctx,struct fd_resource * rsc)821 fd6_rebind_resource(struct fd_context *ctx, struct fd_resource *rsc) assert_dt
822 {
823    fd_screen_assert_locked(ctx->screen);
824 
825    if (!(rsc->dirty & FD_DIRTY_TEX))
826       return;
827 
828    struct fd6_context *fd6_ctx = fd6_context(ctx);
829 
830    hash_table_foreach (fd6_ctx->tex_cache, entry) {
831       struct fd6_texture_state *state = (struct fd6_texture_state *)entry->data;
832 
833       STATIC_ASSERT(ARRAY_SIZE(state->view_rsc_seqno) == ARRAY_SIZE(state->key.view_seqno));
834 
835       for (unsigned i = 0; i < ARRAY_SIZE(state->view_rsc_seqno); i++) {
836          if (rsc->seqno == state->view_rsc_seqno[i]) {
837             struct fd6_texture_state *tex =
838                   (struct fd6_texture_state *)entry->data;
839             tex->invalidate = true;
840             fd6_ctx->tex_cache_needs_invalidate = true;
841          }
842       }
843    }
844 }
845 
846 void
fd6_texture_init(struct pipe_context * pctx)847 fd6_texture_init(struct pipe_context *pctx) disable_thread_safety_analysis
848 {
849    struct fd_context *ctx = fd_context(pctx);
850    struct fd6_context *fd6_ctx = fd6_context(ctx);
851 
852    pctx->create_sampler_state = fd6_sampler_state_create;
853    pctx->delete_sampler_state = fd6_sampler_state_delete;
854    pctx->bind_sampler_states = fd_sampler_states_bind;
855 
856    pctx->create_sampler_view = fd6_sampler_view_create;
857    pctx->sampler_view_destroy = fd6_sampler_view_destroy;
858    pctx->set_sampler_views = fd6_set_sampler_views;
859 
860    ctx->rebind_resource = fd6_rebind_resource;
861 
862    fd6_ctx->bcolor_cache =
863          _mesa_hash_table_create(NULL, bcolor_key_hash, bcolor_key_equals);
864    fd6_ctx->bcolor_mem = fd_bo_new(ctx->screen->dev,
865                                    FD6_MAX_BORDER_COLORS * FD6_BORDER_COLOR_SIZE,
866                                    0, "bcolor");
867 
868    fd_context_add_private_bo(ctx, fd6_ctx->bcolor_mem);
869 
870    fd6_ctx->tex_cache = _mesa_hash_table_create(NULL, tex_key_hash, tex_key_equals);
871    util_idalloc_init(&fd6_ctx->tex_ids, 256);
872 }
873 
874 void
fd6_texture_fini(struct pipe_context * pctx)875 fd6_texture_fini(struct pipe_context *pctx)
876 {
877    struct fd_context *ctx = fd_context(pctx);
878    struct fd6_context *fd6_ctx = fd6_context(ctx);
879 
880    fd_screen_lock(ctx->screen);
881 
882    hash_table_foreach (fd6_ctx->tex_cache, entry) {
883       remove_tex_entry(fd6_ctx, entry);
884    }
885 
886    fd_screen_unlock(ctx->screen);
887 
888    util_idalloc_fini(&fd6_ctx->tex_ids);
889    ralloc_free(fd6_ctx->tex_cache);
890    fd_bo_del(fd6_ctx->bcolor_mem);
891    ralloc_free(fd6_ctx->bcolor_cache);
892 }
893