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>
45 etna_create_sampler_state_desc(struct pipe_context
*pipe
,
46 const struct pipe_sampler_state
*ss
)
48 struct etna_sampler_state_desc
*cs
= CALLOC_STRUCT(etna_sampler_state_desc
);
54 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_UWRAP(translate_texture_wrapmode(ss
->wrap_s
)) |
55 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_VWRAP(translate_texture_wrapmode(ss
->wrap_t
)) |
56 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_WWRAP(translate_texture_wrapmode(ss
->wrap_r
)) |
57 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MIN(translate_texture_filter(ss
->min_img_filter
)) |
58 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MIP(translate_texture_mipfilter(ss
->min_mip_filter
)) |
59 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MAG(translate_texture_filter(ss
->mag_img_filter
)) |
60 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_UNK21
;
61 /* no ROUND_UV bit? */
62 cs
->SAMP_CTRL1
= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_UNK1
;
63 uint32_t min_lod_fp8
= MIN2(etna_float_to_fixp88(ss
->min_lod
), 0xfff);
64 uint32_t max_lod_fp8
= MIN2(etna_float_to_fixp88(ss
->max_lod
), 0xfff);
65 uint32_t max_lod_min
= ss
->min_img_filter
!= ss
->mag_img_filter
? 4 : 0;
67 if (ss
->min_mip_filter
!= PIPE_TEX_MIPFILTER_NONE
) {
69 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MAX(MAX2(max_lod_fp8
, max_lod_min
)) |
70 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MIN(min_lod_fp8
);
73 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MAX(MAX2(max_lod_fp8
, max_lod_min
)) |
74 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MIN(min_lod_fp8
);
77 VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS_BIAS(etna_float_to_fixp88(ss
->lod_bias
)) |
78 COND(ss
->lod_bias
!= 0.0, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS_ENABLE
);
84 etna_delete_sampler_state_desc(struct pipe_context
*pctx
, void *ss
)
89 static struct pipe_sampler_view
*
90 etna_create_sampler_view_desc(struct pipe_context
*pctx
, struct pipe_resource
*prsc
,
91 const struct pipe_sampler_view
*so
)
93 const struct util_format_description
*desc
= util_format_description(so
->format
);
94 struct etna_sampler_view_desc
*sv
= CALLOC_STRUCT(etna_sampler_view_desc
);
95 struct etna_context
*ctx
= etna_context(pctx
);
96 const uint32_t format
= translate_texture_format(so
->format
);
97 const bool ext
= !!(format
& EXT_FORMAT
);
98 const bool astc
= !!(format
& ASTC_FORMAT
);
99 const uint32_t swiz
= get_texture_swiz(so
->format
, so
->swizzle_r
,
100 so
->swizzle_g
, so
->swizzle_b
,
106 struct etna_resource
*res
= etna_texture_handle_incompatible(pctx
, prsc
);
113 pipe_reference_init(&sv
->base
.reference
, 1);
114 sv
->base
.texture
= NULL
;
115 pipe_resource_reference(&sv
->base
.texture
, prsc
);
116 sv
->base
.context
= pctx
;
118 /* Determine whether target supported */
119 uint32_t target_hw
= translate_texture_target(sv
->base
.target
);
120 if (target_hw
== ETNA_NO_MATCH
) {
121 BUG("Unhandled texture target");
126 /* Texture descriptor sampler bits */
127 if (util_format_is_srgb(so
->format
))
128 sv
->SAMP_CTRL1
|= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_SRGB
;
130 if (texture_use_int_filter(so
, true))
131 sv
->SAMP_CTRL0
|= VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_INT_FILTER
;
133 /* Create texture descriptor */
134 sv
->bo
= etna_bo_new(ctx
->screen
->dev
, 0x100, DRM_ETNA_GEM_CACHE_WC
);
138 uint32_t *buf
= etna_bo_map(sv
->bo
);
139 etna_bo_cpu_prep(sv
->bo
, DRM_ETNA_PREP_WRITE
);
140 memset(buf
, 0, 0x100);
142 /** GC7000 needs the size of the BASELOD level */
143 uint32_t base_width
= u_minify(res
->base
.width0
, sv
->base
.u
.tex
.first_level
);
144 uint32_t base_height
= u_minify(res
->base
.height0
, sv
->base
.u
.tex
.first_level
);
145 uint32_t base_depth
= u_minify(res
->base
.depth0
, sv
->base
.u
.tex
.first_level
);
146 bool is_array
= false;
147 bool sint
= util_format_is_pure_sint(so
->format
);
149 if (sv
->base
.target
== PIPE_TEXTURE_1D_ARRAY
) {
151 base_height
= res
->base
.array_size
;
152 } else if (sv
->base
.target
== PIPE_TEXTURE_2D_ARRAY
) {
154 base_depth
= res
->base
.array_size
;
157 #define DESC_SET(x, y) buf[(TEXDESC_##x)>>2] = (y)
158 DESC_SET(CONFIG0
, COND(!ext
&& !astc
, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format
))
159 | VIVS_TE_SAMPLER_CONFIG0_TYPE(target_hw
) |
160 COND(res
->layout
== ETNA_LAYOUT_LINEAR
&& !util_format_is_compressed(so
->format
),
161 VIVS_TE_SAMPLER_CONFIG0_ADDRESSING_MODE(TEXTURE_ADDRESSING_MODE_LINEAR
)));
162 DESC_SET(CONFIG1
, COND(ext
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format
)) |
163 COND(astc
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC
)) |
164 COND(is_array
, VIVS_TE_SAMPLER_CONFIG1_TEXTURE_ARRAY
) |
165 VIVS_TE_SAMPLER_CONFIG1_HALIGN(res
->halign
) | swiz
);
166 DESC_SET(CONFIG2
, 0x00030000 |
167 COND(sint
&& desc
->channel
[0].size
== 8, TE_SAMPLER_CONFIG2_SIGNED_INT8
) |
168 COND(sint
&& desc
->channel
[0].size
== 16, TE_SAMPLER_CONFIG2_SIGNED_INT16
));
169 DESC_SET(LINEAR_STRIDE
, res
->levels
[0].stride
);
170 DESC_SET(VOLUME
, etna_log2_fixp88(base_depth
));
171 DESC_SET(SLICE
, res
->levels
[0].layer_stride
);
172 DESC_SET(3D_CONFIG
, VIVS_TE_SAMPLER_3D_CONFIG_DEPTH(base_depth
));
173 DESC_SET(ASTC0
, COND(astc
, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format
)) |
174 VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
175 VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
176 VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc));
177 DESC_SET(BASELOD
, TEXDESC_BASELOD_BASELOD(sv
->base
.u
.tex
.first_level
) |
178 TEXDESC_BASELOD_MAXLOD(MIN2(sv
->base
.u
.tex
.last_level
, res
->base
.last_level
)));
179 DESC_SET(LOG_SIZE_EXT
, TEXDESC_LOG_SIZE_EXT_WIDTH(etna_log2_fixp88(base_width
)) |
180 TEXDESC_LOG_SIZE_EXT_HEIGHT(etna_log2_fixp88(base_height
)));
181 DESC_SET(SIZE
, VIVS_TE_SAMPLER_SIZE_WIDTH(base_width
) |
182 VIVS_TE_SAMPLER_SIZE_HEIGHT(base_height
));
183 for (int lod
= 0; lod
<= res
->base
.last_level
; ++lod
)
184 DESC_SET(LOD_ADDR(lod
), etna_bo_gpu_va(res
->bo
) + res
->levels
[lod
].offset
);
187 etna_bo_cpu_fini(sv
->bo
);
189 sv
->DESC_ADDR
.bo
= sv
->bo
;
190 sv
->DESC_ADDR
.offset
= 0;
191 sv
->DESC_ADDR
.flags
= ETNA_RELOC_READ
;
200 etna_sampler_view_update_descriptor(struct etna_context
*ctx
,
201 struct etna_cmd_stream
*stream
,
202 struct etna_sampler_view_desc
*sv
)
204 /* TODO: this should instruct the kernel to update the descriptor when the
205 * bo is submitted. For now, just prevent the bo from being freed
206 * while it is in use indirectly.
208 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
210 res
= etna_resource(res
->texture
);
212 /* No need to ref LOD levels individually as they'll always come from the same bo */
213 etna_cmd_stream_ref_bo(stream
, res
->bo
, ETNA_RELOC_READ
);
217 etna_sampler_view_desc_destroy(struct pipe_context
*pctx
,
218 struct pipe_sampler_view
*so
)
220 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(so
);
221 pipe_resource_reference(&sv
->base
.texture
, NULL
);
227 etna_emit_texture_desc(struct etna_context
*ctx
)
229 struct etna_cmd_stream
*stream
= ctx
->stream
;
230 uint32_t active_samplers
= active_samplers_bits(ctx
);
231 uint32_t dirty
= ctx
->dirty
;
233 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
234 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
235 if ((1 << x
) & active_samplers
) {
236 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
237 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
238 struct etna_reloc LOD_ADDR_0
;
243 etna_set_state(stream
, VIVS_TS_SAMPLER_CONFIG(x
), sv
->ts
.TS_SAMPLER_CONFIG
);
244 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_STATUS_BASE(x
), &sv
->ts
.TS_SAMPLER_STATUS_BASE
);
245 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE
);
246 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE2(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE2
);
248 LOD_ADDR_0
.bo
= res
->bo
;
249 LOD_ADDR_0
.offset
= res
->levels
[0].offset
;
250 LOD_ADDR_0
.flags
= ETNA_RELOC_READ
;
252 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_SURFACE_BASE(x
), &LOD_ADDR_0
);
257 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLERS
| ETNA_DIRTY_SAMPLER_VIEWS
))) {
258 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
259 if ((1 << x
) & active_samplers
) {
260 struct etna_sampler_state_desc
*ss
= etna_sampler_state_desc(ctx
->sampler
[x
]);
261 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
262 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_TX_CTRL(x
),
263 COND(sv
->ts
.enable
, VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_ENABLE
) |
264 VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_MODE(sv
->ts
.mode
) |
265 VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_INDEX(x
));
266 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL0(x
), ss
->SAMP_CTRL0
| sv
->SAMP_CTRL0
);
267 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL1(x
), ss
->SAMP_CTRL1
| sv
->SAMP_CTRL1
);
268 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX(x
), ss
->SAMP_LOD_MINMAX
);
269 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS(x
), ss
->SAMP_LOD_BIAS
);
274 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
275 /* Set texture descriptors */
276 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
277 if ((1 << x
) & ctx
->dirty_sampler_views
) {
278 if ((1 << x
) & active_samplers
) {
279 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
280 etna_sampler_view_update_descriptor(ctx
, stream
, sv
);
281 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &sv
->DESC_ADDR
);
283 /* dummy texture descriptors for unused samplers */
284 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &ctx
->DUMMY_DESC_ADDR
);
290 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
291 /* Invalidate all dirty sampler views.
293 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
294 if ((1 << x
) & ctx
->dirty_sampler_views
) {
295 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_INVALIDATE
,
296 VIVS_NTE_DESCRIPTOR_INVALIDATE_UNK29
|
297 VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX(x
));
303 static struct etna_sampler_ts
*
304 etna_ts_for_sampler_view_state(struct pipe_sampler_view
*pview
)
306 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(pview
);
311 etna_texture_desc_init(struct pipe_context
*pctx
)
313 struct etna_context
*ctx
= etna_context(pctx
);
314 DBG("etnaviv: Using descriptor-based texturing\n");
315 ctx
->base
.create_sampler_state
= etna_create_sampler_state_desc
;
316 ctx
->base
.delete_sampler_state
= etna_delete_sampler_state_desc
;
317 ctx
->base
.create_sampler_view
= etna_create_sampler_view_desc
;
318 ctx
->base
.sampler_view_destroy
= etna_sampler_view_desc_destroy
;
319 ctx
->emit_texture_state
= etna_emit_texture_desc
;
320 ctx
->ts_for_sampler_view
= etna_ts_for_sampler_view_state
;