2 * Copyright (c) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
25 * Wladimir J. van der Laan <laanwj@gmail.com>
28 #include "etnaviv_texture_desc.h"
30 #include "hw/common.xml.h"
31 #include "hw/texdesc_3d.xml.h"
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"
42 #include <drm_fourcc.h>
44 struct etna_sampler_state_desc
{
45 struct pipe_sampler_state base
;
48 uint32_t SAMP_LOD_MINMAX
;
49 uint32_t SAMP_LOD_BIAS
;
50 uint32_t SAMP_ANISOTROPY
;
53 static inline struct etna_sampler_state_desc
*
54 etna_sampler_state_desc(struct pipe_sampler_state
*samp
)
56 return (struct etna_sampler_state_desc
*)samp
;
59 struct etna_sampler_view_desc
{
60 struct pipe_sampler_view base
;
61 /* format-dependent merged with sampler state */
66 struct etna_reloc DESC_ADDR
;
67 struct etna_sampler_ts ts
;
70 static inline struct etna_sampler_view_desc
*
71 etna_sampler_view_desc(struct pipe_sampler_view
*view
)
73 return (struct etna_sampler_view_desc
*)view
;
77 etna_create_sampler_state_desc(struct pipe_context
*pipe
,
78 const struct pipe_sampler_state
*ss
)
80 struct etna_sampler_state_desc
*cs
= CALLOC_STRUCT(etna_sampler_state_desc
);
81 const bool ansio
= ss
->max_anisotropy
> 1;
87 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_UWRAP(translate_texture_wrapmode(ss
->wrap_s
)) |
88 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_VWRAP(translate_texture_wrapmode(ss
->wrap_t
)) |
89 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_WWRAP(translate_texture_wrapmode(ss
->wrap_r
)) |
90 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MIN(translate_texture_filter(ss
->min_img_filter
)) |
91 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MIP(translate_texture_mipfilter(ss
->min_mip_filter
)) |
92 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MAG(translate_texture_filter(ss
->mag_img_filter
)) |
93 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_UNK21
;
94 /* no ROUND_UV bit? */
95 cs
->SAMP_CTRL1
= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_UNK1
;
96 uint32_t min_lod_fp8
= MIN2(etna_float_to_fixp88(ss
->min_lod
), 0xfff);
97 uint32_t max_lod_fp8
= MIN2(etna_float_to_fixp88(ss
->max_lod
), 0xfff);
98 uint32_t max_lod_min
= ss
->min_img_filter
!= ss
->mag_img_filter
? 4 : 0;
100 if (ss
->min_mip_filter
!= PIPE_TEX_MIPFILTER_NONE
) {
101 cs
->SAMP_LOD_MINMAX
=
102 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MAX(MAX2(max_lod_fp8
, max_lod_min
)) |
103 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MIN(min_lod_fp8
);
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
);
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
));
118 etna_delete_sampler_state_desc(struct pipe_context
*pctx
, void *ss
)
123 static struct pipe_sampler_view
*
124 etna_create_sampler_view_desc(struct pipe_context
*pctx
, struct pipe_resource
*prsc
,
125 const struct pipe_sampler_view
*so
)
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
,
140 struct etna_resource
*res
= etna_texture_handle_incompatible(pctx
, prsc
);
147 pipe_reference_init(&sv
->base
.reference
, 1);
148 sv
->base
.texture
= NULL
;
149 pipe_resource_reference(&sv
->base
.texture
, prsc
);
150 sv
->base
.context
= pctx
;
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");
160 /* Texture descriptor sampler bits */
161 if (util_format_is_srgb(so
->format
))
162 sv
->SAMP_CTRL1
|= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_SRGB
;
164 /* Create texture descriptor */
165 sv
->bo
= etna_bo_new(ctx
->screen
->dev
, 0x100, DRM_ETNA_GEM_CACHE_WC
);
169 uint32_t *buf
= etna_bo_map(sv
->bo
);
170 etna_bo_cpu_prep(sv
->bo
, DRM_ETNA_PREP_WRITE
);
171 memset(buf
, 0, 0x100);
173 /** GC7000 needs the size of the BASELOD level */
174 uint32_t base_width
= u_minify(res
->base
.width0
, sv
->base
.u
.tex
.first_level
);
175 uint32_t base_height
= u_minify(res
->base
.height0
, sv
->base
.u
.tex
.first_level
);
176 uint32_t base_depth
= u_minify(res
->base
.depth0
, sv
->base
.u
.tex
.first_level
);
177 bool is_array
= false;
178 bool sint
= util_format_is_pure_sint(so
->format
);
180 if (sv
->base
.target
== PIPE_TEXTURE_1D_ARRAY
) {
182 base_height
= res
->base
.array_size
;
183 } else if (sv
->base
.target
== PIPE_TEXTURE_2D_ARRAY
) {
185 base_depth
= res
->base
.array_size
;
188 #define DESC_SET(x, y) buf[(TEXDESC_##x)>>2] = (y)
189 DESC_SET(CONFIG0
, COND(!ext
&& !astc
, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format
))
190 | VIVS_TE_SAMPLER_CONFIG0_TYPE(target_hw
) |
191 COND(res
->layout
== ETNA_LAYOUT_LINEAR
&& !util_format_is_compressed(so
->format
),
192 VIVS_TE_SAMPLER_CONFIG0_ADDRESSING_MODE(TEXTURE_ADDRESSING_MODE_LINEAR
)));
193 DESC_SET(CONFIG1
, COND(ext
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format
)) |
194 COND(astc
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC
)) |
195 COND(is_array
, VIVS_TE_SAMPLER_CONFIG1_TEXTURE_ARRAY
) |
196 VIVS_TE_SAMPLER_CONFIG1_HALIGN(res
->halign
) | swiz
);
197 DESC_SET(CONFIG2
, 0x00030000 |
198 COND(sint
&& desc
->channel
[0].size
== 8, TE_SAMPLER_CONFIG2_SIGNED_INT8
) |
199 COND(sint
&& desc
->channel
[0].size
== 16, TE_SAMPLER_CONFIG2_SIGNED_INT16
));
200 DESC_SET(LINEAR_STRIDE
, res
->levels
[0].stride
);
201 DESC_SET(VOLUME
, etna_log2_fixp88(base_depth
));
202 DESC_SET(SLICE
, res
->levels
[0].layer_stride
);
203 DESC_SET(3D_CONFIG
, VIVS_TE_SAMPLER_3D_CONFIG_DEPTH(base_depth
));
204 DESC_SET(ASTC0
, COND(astc
, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format
)) |
205 VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
206 VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
207 VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc));
208 DESC_SET(BASELOD
, TEXDESC_BASELOD_BASELOD(sv
->base
.u
.tex
.first_level
) |
209 TEXDESC_BASELOD_MAXLOD(MIN2(sv
->base
.u
.tex
.last_level
, res
->base
.last_level
)));
210 DESC_SET(LOG_SIZE_EXT
, TEXDESC_LOG_SIZE_EXT_WIDTH(etna_log2_fixp88(base_width
)) |
211 TEXDESC_LOG_SIZE_EXT_HEIGHT(etna_log2_fixp88(base_height
)));
212 DESC_SET(SIZE
, VIVS_TE_SAMPLER_SIZE_WIDTH(base_width
) |
213 VIVS_TE_SAMPLER_SIZE_HEIGHT(base_height
));
214 for (int lod
= 0; lod
<= res
->base
.last_level
; ++lod
)
215 DESC_SET(LOD_ADDR(lod
), etna_bo_gpu_va(res
->bo
) + res
->levels
[lod
].offset
);
218 etna_bo_cpu_fini(sv
->bo
);
220 sv
->DESC_ADDR
.bo
= sv
->bo
;
221 sv
->DESC_ADDR
.offset
= 0;
222 sv
->DESC_ADDR
.flags
= ETNA_RELOC_READ
;
231 etna_sampler_view_update_descriptor(struct etna_context
*ctx
,
232 struct etna_cmd_stream
*stream
,
233 struct etna_sampler_view_desc
*sv
)
235 /* TODO: this should instruct the kernel to update the descriptor when the
236 * bo is submitted. For now, just prevent the bo from being freed
237 * while it is in use indirectly.
239 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
241 res
= etna_resource(res
->texture
);
243 /* No need to ref LOD levels individually as they'll always come from the same bo */
244 etna_cmd_stream_ref_bo(stream
, res
->bo
, ETNA_RELOC_READ
);
248 etna_sampler_view_desc_destroy(struct pipe_context
*pctx
,
249 struct pipe_sampler_view
*so
)
251 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(so
);
252 pipe_resource_reference(&sv
->base
.texture
, NULL
);
258 etna_emit_texture_desc(struct etna_context
*ctx
)
260 struct etna_cmd_stream
*stream
= ctx
->stream
;
261 uint32_t active_samplers
= active_samplers_bits(ctx
);
262 uint32_t dirty
= ctx
->dirty
;
264 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
265 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
266 if ((1 << x
) & active_samplers
) {
267 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
268 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
269 struct etna_reloc LOD_ADDR_0
;
274 etna_set_state(stream
, VIVS_TS_SAMPLER_CONFIG(x
), sv
->ts
.TS_SAMPLER_CONFIG
);
275 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_STATUS_BASE(x
), &sv
->ts
.TS_SAMPLER_STATUS_BASE
);
276 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE
);
277 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE2(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE2
);
279 LOD_ADDR_0
.bo
= res
->bo
;
280 LOD_ADDR_0
.offset
= res
->levels
[0].offset
;
281 LOD_ADDR_0
.flags
= ETNA_RELOC_READ
;
283 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_SURFACE_BASE(x
), &LOD_ADDR_0
);
288 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLERS
| ETNA_DIRTY_SAMPLER_VIEWS
))) {
289 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
290 if ((1 << x
) & active_samplers
) {
291 struct etna_sampler_state_desc
*ss
= etna_sampler_state_desc(ctx
->sampler
[x
]);
292 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
294 if (texture_use_int_filter(&sv
->base
, &ss
->base
, true))
295 sv
->SAMP_CTRL0
|= VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_INT_FILTER
;
297 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_TX_CTRL(x
),
298 COND(sv
->ts
.enable
, VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_ENABLE
) |
299 VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_MODE(sv
->ts
.mode
) |
300 VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_INDEX(x
));
301 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL0(x
), ss
->SAMP_CTRL0
| sv
->SAMP_CTRL0
);
302 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL1(x
), ss
->SAMP_CTRL1
| sv
->SAMP_CTRL1
);
303 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX(x
), ss
->SAMP_LOD_MINMAX
);
304 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS(x
), ss
->SAMP_LOD_BIAS
);
305 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_ANISOTROPY(x
), ss
->SAMP_ANISOTROPY
);
310 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
311 /* Set texture descriptors */
312 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
313 if ((1 << x
) & ctx
->dirty_sampler_views
) {
314 if ((1 << x
) & active_samplers
) {
315 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
316 etna_sampler_view_update_descriptor(ctx
, stream
, sv
);
317 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &sv
->DESC_ADDR
);
319 /* dummy texture descriptors for unused samplers */
320 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &ctx
->DUMMY_DESC_ADDR
);
326 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
327 /* Invalidate all dirty sampler views.
329 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
330 if ((1 << x
) & ctx
->dirty_sampler_views
) {
331 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_INVALIDATE
,
332 VIVS_NTE_DESCRIPTOR_INVALIDATE_UNK29
|
333 VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX(x
));
339 static struct etna_sampler_ts
*
340 etna_ts_for_sampler_view_state(struct pipe_sampler_view
*pview
)
342 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(pview
);
347 etna_texture_desc_init(struct pipe_context
*pctx
)
349 struct etna_context
*ctx
= etna_context(pctx
);
350 DBG("etnaviv: Using descriptor-based texturing\n");
351 ctx
->base
.create_sampler_state
= etna_create_sampler_state_desc
;
352 ctx
->base
.delete_sampler_state
= etna_delete_sampler_state_desc
;
353 ctx
->base
.create_sampler_view
= etna_create_sampler_view_desc
;
354 ctx
->base
.sampler_view_destroy
= etna_sampler_view_desc_destroy
;
355 ctx
->emit_texture_state
= etna_emit_texture_desc
;
356 ctx
->ts_for_sampler_view
= etna_ts_for_sampler_view_state
;