xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (c) 2017 Etnaviv Project
3  * Copyright (C) 2017 Zodiac Inflight Innovations
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, sub license,
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
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the 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 NON-INFRINGEMENT. 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
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Wladimir J. van der Laan <[email protected]>
26  */
27 
28 #include "etnaviv_texture_desc.h"
29 
30 #include "hw/common.xml.h"
31 #include "hw/texdesc_3d.xml.h"
32 
33 #include "etnaviv_clear_blit.h"
34 #include "etnaviv_context.h"
35 #include "etnaviv_emit.h"
36 #include "etnaviv_format.h"
37 #include "etnaviv_translate.h"
38 #include "etnaviv_texture.h"
39 #include "util/u_inlines.h"
40 #include "util/u_memory.h"
41 
42 #include <drm_fourcc.h>
43 
44 struct etna_sampler_state_desc {
45    struct pipe_sampler_state base;
46    uint32_t SAMP_CTRL0;
47    uint32_t SAMP_CTRL1;
48    uint32_t SAMP_LOD_MINMAX;
49    uint32_t SAMP_LOD_BIAS;
50    uint32_t SAMP_ANISOTROPY;
51 };
52 
53 static inline struct etna_sampler_state_desc *
etna_sampler_state_desc(struct pipe_sampler_state * samp)54 etna_sampler_state_desc(struct pipe_sampler_state *samp)
55 {
56    return (struct etna_sampler_state_desc *)samp;
57 }
58 
59 struct etna_sampler_view_desc {
60    struct pipe_sampler_view base;
61    /* format-dependent merged with sampler state */
62    uint32_t SAMP_CTRL0;
63    uint32_t SAMP_CTRL0_MASK;
64    uint32_t SAMP_CTRL1;
65 
66    struct pipe_resource *res;
67    struct etna_reloc DESC_ADDR;
68    struct etna_sampler_ts ts;
69 };
70 
71 static inline struct etna_sampler_view_desc *
etna_sampler_view_desc(struct pipe_sampler_view * view)72 etna_sampler_view_desc(struct pipe_sampler_view *view)
73 {
74    return (struct etna_sampler_view_desc *)view;
75 }
76 
77 static void *
etna_create_sampler_state_desc(struct pipe_context * pipe,const struct pipe_sampler_state * ss)78 etna_create_sampler_state_desc(struct pipe_context *pipe,
79                           const struct pipe_sampler_state *ss)
80 {
81    struct etna_sampler_state_desc *cs = CALLOC_STRUCT(etna_sampler_state_desc);
82    const bool ansio = ss->max_anisotropy > 1;
83 
84    if (!cs)
85       return NULL;
86 
87    cs->base = *ss;
88 
89    cs->SAMP_CTRL0 =
90       VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_UWRAP(translate_texture_wrapmode(ss->wrap_s)) |
91       VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_VWRAP(translate_texture_wrapmode(ss->wrap_t)) |
92       VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_WWRAP(translate_texture_wrapmode(ss->wrap_r)) |
93       VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MIN(translate_texture_filter(ss->min_img_filter)) |
94       VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MIP(translate_texture_mipfilter(ss->min_mip_filter)) |
95       VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MAG(translate_texture_filter(ss->mag_img_filter)) |
96       COND(ss->compare_mode, VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_COMPARE_ENABLE) |
97       VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_COMPARE_FUNC(translate_texture_compare(ss->compare_func)) |
98       VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_UNK21;
99       /* no ROUND_UV bit? */
100    cs->SAMP_CTRL1 = VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_UNK1;
101    uint32_t min_lod_fp8 = MIN2(etna_float_to_fixp88(ss->min_lod), 0xfff);
102    uint32_t max_lod_fp8 = MIN2(etna_float_to_fixp88(ss->max_lod), 0xfff);
103    uint32_t max_lod_min = ss->min_img_filter != ss->mag_img_filter ? 4 : 0;
104 
105    cs->SAMP_LOD_MINMAX =
106       VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MAX(MAX2(max_lod_fp8, max_lod_min)) |
107       VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MIN(min_lod_fp8);
108 
109    cs->SAMP_LOD_BIAS =
110       VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS_BIAS(etna_float_to_fixp88(ss->lod_bias)) |
111       COND(ss->lod_bias != 0.0, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS_ENABLE);
112    cs->SAMP_ANISOTROPY = COND(ansio, etna_log2_fixp88(ss->max_anisotropy));
113 
114    return cs;
115 }
116 
117 static void
etna_delete_sampler_state_desc(struct pipe_context * pctx,void * ss)118 etna_delete_sampler_state_desc(struct pipe_context *pctx, void *ss)
119 {
120    FREE(ss);
121 }
122 
123 static struct pipe_sampler_view *
etna_create_sampler_view_desc(struct pipe_context * pctx,struct pipe_resource * prsc,const struct pipe_sampler_view * so)124 etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *prsc,
125                          const struct pipe_sampler_view *so)
126 {
127    const struct util_format_description *desc = util_format_description(so->format);
128    struct etna_sampler_view_desc *sv = CALLOC_STRUCT(etna_sampler_view_desc);
129    struct etna_context *ctx = etna_context(pctx);
130    const uint32_t format = translate_texture_format(so->format);
131    const bool ext = !!(format & EXT_FORMAT);
132    const bool astc = !!(format & ASTC_FORMAT);
133    const uint32_t swiz = get_texture_swiz(so->format, so->swizzle_r,
134                                           so->swizzle_g, so->swizzle_b,
135                                           so->swizzle_a);
136    unsigned suballoc_offset;
137 
138    if (!sv)
139       return NULL;
140 
141    struct etna_resource *res = etna_texture_handle_incompatible(pctx, prsc);
142    if (!res)
143       goto error;
144 
145    sv->base = *so;
146    pipe_reference_init(&sv->base.reference, 1);
147    sv->base.texture = NULL;
148    pipe_resource_reference(&sv->base.texture, prsc);
149    sv->base.context = pctx;
150    sv->SAMP_CTRL0_MASK = 0xffffffff;
151 
152    /* Determine whether target supported */
153    uint32_t target_hw = translate_texture_target(sv->base.target);
154    if (target_hw == ETNA_NO_MATCH) {
155       BUG("Unhandled texture target");
156       goto error;
157    }
158 
159    /* Texture descriptor sampler bits */
160    if (util_format_is_srgb(so->format))
161       sv->SAMP_CTRL1 |= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_SRGB;
162 
163    /* Create texture descriptor */
164    u_suballocator_alloc(&ctx->tex_desc_allocator, 256, 64,
165                         &suballoc_offset, &sv->res);
166    if (!sv->res)
167       goto error;
168 
169    uint32_t *buf = etna_bo_map(etna_resource(sv->res)->bo) + suballoc_offset;
170 
171    /** GC7000 needs the size of the BASELOD level */
172    uint32_t base_width = u_minify(res->base.width0, sv->base.u.tex.first_level);
173    uint32_t base_height = u_minify(res->base.height0, sv->base.u.tex.first_level);
174    uint32_t base_depth = u_minify(res->base.depth0, sv->base.u.tex.first_level);
175    bool is_array = false;
176    bool sint = util_format_is_pure_sint(so->format);
177 
178    switch(sv->base.target) {
179    case PIPE_TEXTURE_1D:
180       target_hw = TEXTURE_TYPE_2D;
181       sv->SAMP_CTRL0_MASK = ~VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_VWRAP__MASK;
182       sv->SAMP_CTRL0 = VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_VWRAP(TEXTURE_WRAPMODE_REPEAT);
183       break;
184    case PIPE_TEXTURE_1D_ARRAY:
185       is_array = true;
186       base_height = res->base.array_size;
187       break;
188    case PIPE_TEXTURE_2D_ARRAY:
189       is_array = true;
190       base_depth = res->base.array_size;
191       break;
192    default:
193       break;
194    }
195 
196 #define DESC_SET(x, y) buf[(TEXDESC_##x)>>2] = (y)
197    DESC_SET(CONFIG0, COND(!ext && !astc, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format))
198                    | VIVS_TE_SAMPLER_CONFIG0_TYPE(target_hw) |
199                    COND(res->layout == ETNA_LAYOUT_LINEAR && !util_format_is_compressed(so->format),
200                         VIVS_TE_SAMPLER_CONFIG0_ADDRESSING_MODE(TEXTURE_ADDRESSING_MODE_LINEAR)));
201    DESC_SET(CONFIG1, COND(ext, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format)) |
202                      COND(astc, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC)) |
203                      COND(is_array, VIVS_TE_SAMPLER_CONFIG1_TEXTURE_ARRAY) |
204                      VIVS_TE_SAMPLER_CONFIG1_HALIGN(res->halign) | swiz);
205    DESC_SET(CONFIG2, 0x00030000 |
206          COND(sint && desc->channel[0].size == 8, TE_SAMPLER_CONFIG2_SIGNED_INT8) |
207          COND(sint && desc->channel[0].size == 16, TE_SAMPLER_CONFIG2_SIGNED_INT16));
208    DESC_SET(LINEAR_STRIDE, res->levels[0].stride);
209    DESC_SET(VOLUME, etna_log2_fixp88(base_depth));
210    DESC_SET(SLICE, res->levels[0].layer_stride);
211    DESC_SET(3D_CONFIG, VIVS_TE_SAMPLER_3D_CONFIG_DEPTH(base_depth));
212    DESC_SET(ASTC0, COND(astc, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format)) |
213                    VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
214                    VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
215                    VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc));
216    DESC_SET(BASELOD, TEXDESC_BASELOD_BASELOD(sv->base.u.tex.first_level) |
217                      TEXDESC_BASELOD_MAXLOD(MIN2(sv->base.u.tex.last_level, res->base.last_level)));
218    DESC_SET(LOG_SIZE_EXT, TEXDESC_LOG_SIZE_EXT_WIDTH(etna_log2_fixp88(base_width)) |
219                           TEXDESC_LOG_SIZE_EXT_HEIGHT(etna_log2_fixp88(base_height)));
220    DESC_SET(SIZE, VIVS_TE_SAMPLER_SIZE_WIDTH(base_width) |
221                   VIVS_TE_SAMPLER_SIZE_HEIGHT(base_height));
222    for (int lod = 0; lod <= res->base.last_level; ++lod)
223       DESC_SET(LOD_ADDR(lod), etna_bo_gpu_va(res->bo) + res->levels[lod].offset);
224 #undef DESC_SET
225 
226    sv->DESC_ADDR.bo = etna_resource(sv->res)->bo;
227    sv->DESC_ADDR.offset = suballoc_offset;
228    sv->DESC_ADDR.flags = ETNA_RELOC_READ;
229 
230    return &sv->base;
231 
232 error:
233    free(sv);
234    return NULL;
235 }
236 
237 static void
etna_sampler_view_update_descriptor(struct etna_context * ctx,struct etna_cmd_stream * stream,struct etna_sampler_view_desc * sv)238 etna_sampler_view_update_descriptor(struct etna_context *ctx,
239                                     struct etna_cmd_stream *stream,
240                                     struct etna_sampler_view_desc *sv)
241 {
242    struct etna_resource *res = etna_resource(sv->base.texture);
243 
244    if (res->texture) {
245       res = etna_resource(res->texture);
246    }
247 
248    /* No need to ref LOD levels individually as they'll always come from the same bo */
249    etna_cmd_stream_ref_bo(stream, res->bo, ETNA_RELOC_READ);
250 }
251 
252 static void
etna_sampler_view_desc_destroy(struct pipe_context * pctx,struct pipe_sampler_view * so)253 etna_sampler_view_desc_destroy(struct pipe_context *pctx,
254                           struct pipe_sampler_view *so)
255 {
256    struct etna_sampler_view_desc *sv = etna_sampler_view_desc(so);
257 
258    pipe_resource_reference(&sv->base.texture, NULL);
259    pipe_resource_reference(&sv->res, NULL);
260    FREE(sv);
261 }
262 
263 static void
etna_emit_texture_desc(struct etna_context * ctx)264 etna_emit_texture_desc(struct etna_context *ctx)
265 {
266    struct etna_cmd_stream *stream = ctx->stream;
267    uint32_t active_samplers = active_samplers_bits(ctx);
268    uint32_t dirty = ctx->dirty;
269 
270    if (unlikely(dirty & ETNA_DIRTY_SAMPLER_VIEWS)) {
271       for (int x = 0; x < VIVS_TS_SAMPLER__LEN; ++x) {
272          if ((1 << x) & active_samplers) {
273             struct etna_sampler_view_desc *sv = etna_sampler_view_desc(ctx->sampler_view[x]);
274             struct etna_resource *res = etna_resource(sv->base.texture);
275             struct etna_reloc LOD_ADDR_0;
276 
277             if (!sv->ts.enable)
278                continue;
279 
280             etna_set_state(stream, VIVS_TS_SAMPLER_CONFIG(x), sv->ts.TS_SAMPLER_CONFIG);
281             etna_set_state_reloc(stream, VIVS_TS_SAMPLER_STATUS_BASE(x), &sv->ts.TS_SAMPLER_STATUS_BASE);
282             etna_set_state(stream, VIVS_TS_SAMPLER_CLEAR_VALUE(x), sv->ts.TS_SAMPLER_CLEAR_VALUE);
283             etna_set_state(stream, VIVS_TS_SAMPLER_CLEAR_VALUE2(x), sv->ts.TS_SAMPLER_CLEAR_VALUE2);
284 
285             LOD_ADDR_0.bo = res->bo;
286             LOD_ADDR_0.offset = res->levels[0].offset;
287             LOD_ADDR_0.flags = ETNA_RELOC_READ;
288 
289             etna_set_state_reloc(stream, VIVS_TS_SAMPLER_SURFACE_BASE(x), &LOD_ADDR_0);
290          }
291       }
292    }
293 
294    if (unlikely(dirty & (ETNA_DIRTY_SAMPLERS | ETNA_DIRTY_SAMPLER_VIEWS))) {
295       for (int x = 0; x < PIPE_MAX_SAMPLERS; ++x) {
296          if ((1 << x) & active_samplers) {
297             struct etna_sampler_state_desc *ss = etna_sampler_state_desc(ctx->sampler[x]);
298             struct etna_sampler_view_desc *sv = etna_sampler_view_desc(ctx->sampler_view[x]);
299             uint32_t SAMP_CTRL0 = (ss->SAMP_CTRL0 & sv->SAMP_CTRL0_MASK) | sv->SAMP_CTRL0;
300 
301             if (texture_use_int_filter(&sv->base, &ss->base, true))
302                SAMP_CTRL0 |= VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_INT_FILTER;
303 
304             etna_set_state(stream, VIVS_NTE_DESCRIPTOR_TX_CTRL(x),
305                COND(sv->ts.enable, VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_ENABLE) |
306                VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_MODE(sv->ts.mode) |
307                VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_INDEX(x)|
308                COND(sv->ts.comp, VIVS_NTE_DESCRIPTOR_TX_CTRL_COMPRESSION) |
309                COND(!sv->ts.mode, VIVS_NTE_DESCRIPTOR_TX_CTRL_128B_TILE));
310             etna_set_state(stream, VIVS_NTE_DESCRIPTOR_SAMP_CTRL0(x), SAMP_CTRL0);
311             etna_set_state(stream, VIVS_NTE_DESCRIPTOR_SAMP_CTRL1(x), ss->SAMP_CTRL1 | sv->SAMP_CTRL1);
312             etna_set_state(stream, VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX(x), ss->SAMP_LOD_MINMAX);
313             etna_set_state(stream, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS(x), ss->SAMP_LOD_BIAS);
314             etna_set_state(stream, VIVS_NTE_DESCRIPTOR_SAMP_ANISOTROPY(x), ss->SAMP_ANISOTROPY);
315          }
316       }
317    }
318 
319    if (unlikely(dirty & ETNA_DIRTY_SAMPLER_VIEWS)) {
320       /* Set texture descriptors */
321       for (int x = 0; x < PIPE_MAX_SAMPLERS; ++x) {
322          if ((1 << x) & ctx->dirty_sampler_views) {
323             if ((1 << x) & active_samplers) {
324                struct etna_sampler_view_desc *sv = etna_sampler_view_desc(ctx->sampler_view[x]);
325                etna_sampler_view_update_descriptor(ctx, stream, sv);
326                etna_set_state_reloc(stream, VIVS_NTE_DESCRIPTOR_ADDR(x), &sv->DESC_ADDR);
327             } else if ((1 << x) & ctx->prev_active_samplers){
328                /* dummy texture descriptors for unused samplers */
329                etna_set_state_reloc(stream, VIVS_NTE_DESCRIPTOR_ADDR(x),
330                                     &ctx->screen->dummy_desc_reloc);
331             }
332          }
333       }
334    }
335 
336    if (unlikely(dirty & ETNA_DIRTY_SAMPLER_VIEWS)) {
337       /* Invalidate all dirty sampler views.
338        */
339       for (int x = 0; x < PIPE_MAX_SAMPLERS; ++x) {
340          if ((1 << x) & ctx->dirty_sampler_views) {
341             etna_set_state(stream, VIVS_NTE_DESCRIPTOR_INVALIDATE,
342                   VIVS_NTE_DESCRIPTOR_INVALIDATE_UNK29 |
343                   VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX(x));
344          }
345       }
346    }
347 
348    ctx->prev_active_samplers = active_samplers;
349 }
350 
351 static struct etna_sampler_ts*
etna_ts_for_sampler_view_state(struct pipe_sampler_view * pview)352 etna_ts_for_sampler_view_state(struct pipe_sampler_view *pview)
353 {
354    struct etna_sampler_view_desc *sv = etna_sampler_view_desc(pview);
355    return &sv->ts;
356 }
357 
358 void
etna_texture_desc_init(struct pipe_context * pctx)359 etna_texture_desc_init(struct pipe_context *pctx)
360 {
361    struct etna_context *ctx = etna_context(pctx);
362    DBG("etnaviv: Using descriptor-based texturing\n");
363    ctx->base.create_sampler_state = etna_create_sampler_state_desc;
364    ctx->base.delete_sampler_state = etna_delete_sampler_state_desc;
365    ctx->base.create_sampler_view = etna_create_sampler_view_desc;
366    ctx->base.sampler_view_destroy = etna_sampler_view_desc_destroy;
367    ctx->emit_texture_state = etna_emit_texture_desc;
368    ctx->ts_for_sampler_view = etna_ts_for_sampler_view_state;
369 }
370 
371