• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Valve Corporation
3  * SPDX-License-Identifier: MIT
4  *
5  * Authors:
6  *    Jonathan Marek <jonathan@marek.ca>
7  */
8 
9 #ifndef TU_UTIL_H
10 #define TU_UTIL_H
11 
12 #include "tu_common.h"
13 
14 #include "util/u_math.h"
15 #include "util/format/u_format_pack.h"
16 #include "util/format/u_format_zs.h"
17 #include "compiler/shader_enums.h"
18 
19 #include "vk_util.h"
20 
21 /* Whenever we generate an error, pass it through this function. Useful for
22  * debugging, where we can break on it. Only call at error site, not when
23  * propagating errors. Might be useful to plug in a stack trace here.
24  */
25 
26 VkResult
27 __vk_startup_errorf(struct tu_instance *instance,
28                     VkResult error,
29                     bool force_print,
30                     const char *file,
31                     int line,
32                     const char *format,
33                     ...) PRINTFLIKE(6, 7);
34 
35 /* Prints startup errors if TU_DEBUG=startup is set or on a debug driver
36  * build.
37  */
38 #define vk_startup_errorf(instance, error, format, ...) \
39    __vk_startup_errorf(instance, error, \
40                        instance->debug_flags & TU_DEBUG_STARTUP, \
41                        __FILE__, __LINE__, format, ##__VA_ARGS__)
42 
43 void
44 __tu_finishme(const char *file, int line, const char *format, ...)
45    PRINTFLIKE(3, 4);
46 
47 /**
48  * Print a FINISHME message, including its source location.
49  */
50 #define tu_finishme(format, ...)                                             \
51    do {                                                                      \
52       static bool reported = false;                                          \
53       if (!reported) {                                                       \
54          __tu_finishme(__FILE__, __LINE__, format, ##__VA_ARGS__);           \
55          reported = true;                                                    \
56       }                                                                      \
57    } while (0)
58 
59 #define tu_stub()                                                            \
60    do {                                                                      \
61       tu_finishme("stub %s", __func__);                                      \
62    } while (0)
63 
64 void
65 tu_framebuffer_tiling_config(struct tu_framebuffer *fb,
66                              const struct tu_device *device,
67                              const struct tu_render_pass *pass);
68 
69 #define TU_STAGE_MASK ((1 << MESA_SHADER_STAGES) - 1)
70 
71 #define tu_foreach_stage(stage, stage_bits)                                  \
72    for (gl_shader_stage stage,                                               \
73         __tmp = (gl_shader_stage)((stage_bits) &TU_STAGE_MASK);              \
74         stage = __builtin_ffs(__tmp) - 1, __tmp; __tmp &= ~(1 << (stage)))
75 
76 static inline enum a3xx_msaa_samples
tu_msaa_samples(uint32_t samples)77 tu_msaa_samples(uint32_t samples)
78 {
79    assert(__builtin_popcount(samples) == 1);
80    return util_logbase2(samples);
81 }
82 
83 static inline uint32_t
tu6_stage2opcode(gl_shader_stage stage)84 tu6_stage2opcode(gl_shader_stage stage)
85 {
86    if (stage == MESA_SHADER_FRAGMENT || stage == MESA_SHADER_COMPUTE)
87       return CP_LOAD_STATE6_FRAG;
88    return CP_LOAD_STATE6_GEOM;
89 }
90 
91 static inline enum a6xx_state_block
tu6_stage2texsb(gl_shader_stage stage)92 tu6_stage2texsb(gl_shader_stage stage)
93 {
94    return SB6_VS_TEX + stage;
95 }
96 
97 static inline enum a6xx_state_block
tu6_stage2shadersb(gl_shader_stage stage)98 tu6_stage2shadersb(gl_shader_stage stage)
99 {
100    return SB6_VS_SHADER + stage;
101 }
102 
103 static inline enum a3xx_rop_code
tu6_rop(VkLogicOp op)104 tu6_rop(VkLogicOp op)
105 {
106    /* note: hw enum matches the VK enum, but with the 4 bits reversed */
107    static const uint8_t lookup[] = {
108       [VK_LOGIC_OP_CLEAR]           = ROP_CLEAR,
109       [VK_LOGIC_OP_AND]             = ROP_AND,
110       [VK_LOGIC_OP_AND_REVERSE]     = ROP_AND_REVERSE,
111       [VK_LOGIC_OP_COPY]            = ROP_COPY,
112       [VK_LOGIC_OP_AND_INVERTED]    = ROP_AND_INVERTED,
113       [VK_LOGIC_OP_NO_OP]           = ROP_NOOP,
114       [VK_LOGIC_OP_XOR]             = ROP_XOR,
115       [VK_LOGIC_OP_OR]              = ROP_OR,
116       [VK_LOGIC_OP_NOR]             = ROP_NOR,
117       [VK_LOGIC_OP_EQUIVALENT]      = ROP_EQUIV,
118       [VK_LOGIC_OP_INVERT]          = ROP_INVERT,
119       [VK_LOGIC_OP_OR_REVERSE]      = ROP_OR_REVERSE,
120       [VK_LOGIC_OP_COPY_INVERTED]   = ROP_COPY_INVERTED,
121       [VK_LOGIC_OP_OR_INVERTED]     = ROP_OR_INVERTED,
122       [VK_LOGIC_OP_NAND]            = ROP_NAND,
123       [VK_LOGIC_OP_SET]             = ROP_SET,
124    };
125    assert(op < ARRAY_SIZE(lookup));
126    return lookup[op];
127 }
128 
129 static inline bool
tu6_primtype_line(enum pc_di_primtype type)130 tu6_primtype_line(enum pc_di_primtype type)
131 {
132     switch(type) {
133     case DI_PT_LINELIST:
134     case DI_PT_LINESTRIP:
135     case DI_PT_LINE_ADJ:
136     case DI_PT_LINESTRIP_ADJ:
137        return true;
138     default:
139        return false;
140     }
141 }
142 
143 static inline bool
tu6_primtype_patches(enum pc_di_primtype type)144 tu6_primtype_patches(enum pc_di_primtype type)
145 {
146    return type >= DI_PT_PATCHES0 && type <= DI_PT_PATCHES31;
147 }
148 
149 static inline enum pc_di_primtype
tu6_primtype(VkPrimitiveTopology topology)150 tu6_primtype(VkPrimitiveTopology topology)
151 {
152    static const uint8_t lookup[] = {
153       [VK_PRIMITIVE_TOPOLOGY_POINT_LIST]                    = DI_PT_POINTLIST,
154       [VK_PRIMITIVE_TOPOLOGY_LINE_LIST]                     = DI_PT_LINELIST,
155       [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP]                    = DI_PT_LINESTRIP,
156       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST]                 = DI_PT_TRILIST,
157       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP]                = DI_PT_TRISTRIP,
158       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN]                  = DI_PT_TRIFAN,
159       [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY]      = DI_PT_LINE_ADJ,
160       [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY]     = DI_PT_LINESTRIP_ADJ,
161       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY]  = DI_PT_TRI_ADJ,
162       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY] = DI_PT_TRISTRIP_ADJ,
163       /* Return PATCH0 and update in tu_pipeline_builder_parse_tessellation */
164       [VK_PRIMITIVE_TOPOLOGY_PATCH_LIST]                    = DI_PT_PATCHES0,
165    };
166    assert(topology < ARRAY_SIZE(lookup));
167    return lookup[topology];
168 }
169 
170 static inline enum adreno_compare_func
tu6_compare_func(VkCompareOp op)171 tu6_compare_func(VkCompareOp op)
172 {
173    return (enum adreno_compare_func) op;
174 }
175 
176 static inline enum adreno_stencil_op
tu6_stencil_op(VkStencilOp op)177 tu6_stencil_op(VkStencilOp op)
178 {
179    return (enum adreno_stencil_op) op;
180 }
181 
182 static inline enum adreno_rb_blend_factor
tu6_blend_factor(VkBlendFactor factor)183 tu6_blend_factor(VkBlendFactor factor)
184 {
185    static const uint8_t lookup[] = {
186       [VK_BLEND_FACTOR_ZERO]                    = FACTOR_ZERO,
187       [VK_BLEND_FACTOR_ONE]                     = FACTOR_ONE,
188       [VK_BLEND_FACTOR_SRC_COLOR]               = FACTOR_SRC_COLOR,
189       [VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR]     = FACTOR_ONE_MINUS_SRC_COLOR,
190       [VK_BLEND_FACTOR_DST_COLOR]               = FACTOR_DST_COLOR,
191       [VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR]     = FACTOR_ONE_MINUS_DST_COLOR,
192       [VK_BLEND_FACTOR_SRC_ALPHA]               = FACTOR_SRC_ALPHA,
193       [VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA]     = FACTOR_ONE_MINUS_SRC_ALPHA,
194       [VK_BLEND_FACTOR_DST_ALPHA]               = FACTOR_DST_ALPHA,
195       [VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA]     = FACTOR_ONE_MINUS_DST_ALPHA,
196       [VK_BLEND_FACTOR_CONSTANT_COLOR]          = FACTOR_CONSTANT_COLOR,
197       [VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR]= FACTOR_ONE_MINUS_CONSTANT_COLOR,
198       [VK_BLEND_FACTOR_CONSTANT_ALPHA]          = FACTOR_CONSTANT_ALPHA,
199       [VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA]= FACTOR_ONE_MINUS_CONSTANT_ALPHA,
200       [VK_BLEND_FACTOR_SRC_ALPHA_SATURATE]      = FACTOR_SRC_ALPHA_SATURATE,
201       [VK_BLEND_FACTOR_SRC1_COLOR]              = FACTOR_SRC1_COLOR,
202       [VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR]    = FACTOR_ONE_MINUS_SRC1_COLOR,
203       [VK_BLEND_FACTOR_SRC1_ALPHA]              = FACTOR_SRC1_ALPHA,
204       [VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA]    = FACTOR_ONE_MINUS_SRC1_ALPHA,
205    };
206    assert(factor < ARRAY_SIZE(lookup));
207    return lookup[factor];
208 }
209 
210 static inline enum a3xx_rb_blend_opcode
tu6_blend_op(VkBlendOp op)211 tu6_blend_op(VkBlendOp op)
212 {
213    return (enum a3xx_rb_blend_opcode) op;
214 }
215 
216 static inline enum a6xx_tex_type
tu6_tex_type(VkImageViewType type,bool storage)217 tu6_tex_type(VkImageViewType type, bool storage)
218 {
219    switch (type) {
220    default:
221    case VK_IMAGE_VIEW_TYPE_1D:
222    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
223       return A6XX_TEX_1D;
224    case VK_IMAGE_VIEW_TYPE_2D:
225    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
226       return A6XX_TEX_2D;
227    case VK_IMAGE_VIEW_TYPE_3D:
228       return A6XX_TEX_3D;
229    case VK_IMAGE_VIEW_TYPE_CUBE:
230    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
231       return storage ? A6XX_TEX_2D : A6XX_TEX_CUBE;
232    }
233 }
234 
235 static inline enum a6xx_tex_clamp
tu6_tex_wrap(VkSamplerAddressMode address_mode)236 tu6_tex_wrap(VkSamplerAddressMode address_mode)
237 {
238    uint8_t lookup[] = {
239       [VK_SAMPLER_ADDRESS_MODE_REPEAT]                = A6XX_TEX_REPEAT,
240       [VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT]       = A6XX_TEX_MIRROR_REPEAT,
241       [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE]         = A6XX_TEX_CLAMP_TO_EDGE,
242       [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER]       = A6XX_TEX_CLAMP_TO_BORDER,
243       [VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE]  = A6XX_TEX_MIRROR_CLAMP,
244    };
245    assert(address_mode < ARRAY_SIZE(lookup));
246    return lookup[address_mode];
247 }
248 
249 static inline enum a6xx_tex_filter
tu6_tex_filter(VkFilter filter,unsigned aniso)250 tu6_tex_filter(VkFilter filter, unsigned aniso)
251 {
252    switch (filter) {
253    case VK_FILTER_NEAREST:
254       return A6XX_TEX_NEAREST;
255    case VK_FILTER_LINEAR:
256       return aniso ? A6XX_TEX_ANISO : A6XX_TEX_LINEAR;
257    case VK_FILTER_CUBIC_EXT:
258       return A6XX_TEX_CUBIC;
259    default:
260       unreachable("illegal texture filter");
261       break;
262    }
263 }
264 
265 static inline enum a6xx_reduction_mode
tu6_reduction_mode(VkSamplerReductionMode reduction_mode)266 tu6_reduction_mode(VkSamplerReductionMode reduction_mode)
267 {
268    return (enum a6xx_reduction_mode) reduction_mode;
269 }
270 
271 static inline enum a6xx_depth_format
tu6_pipe2depth(VkFormat format)272 tu6_pipe2depth(VkFormat format)
273 {
274    switch (format) {
275    case VK_FORMAT_D16_UNORM:
276       return DEPTH6_16;
277    case VK_FORMAT_X8_D24_UNORM_PACK32:
278    case VK_FORMAT_D24_UNORM_S8_UINT:
279       return DEPTH6_24_8;
280    case VK_FORMAT_D32_SFLOAT:
281    case VK_FORMAT_D32_SFLOAT_S8_UINT:
282    case VK_FORMAT_S8_UINT:
283       return DEPTH6_32;
284    default:
285       return ~0;
286    }
287 }
288 
289 static inline enum a6xx_polygon_mode
tu6_polygon_mode(VkPolygonMode mode)290 tu6_polygon_mode(VkPolygonMode mode)
291 {
292    switch (mode) {
293    case VK_POLYGON_MODE_POINT:
294       return POLYMODE6_POINTS;
295    case VK_POLYGON_MODE_LINE:
296       return POLYMODE6_LINES;
297    case VK_POLYGON_MODE_FILL:
298       return POLYMODE6_TRIANGLES;
299    default:
300       unreachable("bad polygon mode");
301    }
302 }
303 
304 struct bcolor_entry {
305    uint32_t fp32[4];
306    uint64_t ui16;
307    uint64_t si16;
308    uint64_t fp16;
309    uint16_t rgb565;
310    uint16_t rgb5a1;
311    uint16_t rgba4;
312    uint8_t __pad0[2];
313    uint32_t ui8;
314    uint32_t si8;
315    uint32_t rgb10a2;
316    uint32_t z24; /* also s8? */
317    uint64_t srgb;
318    uint8_t  __pad1[56];
319 } __attribute__((aligned(128)));
320 
321 /* vulkan does not want clamping of integer clear values, differs from u_format
322  * see spec for VkClearColorValue
323  */
324 static inline void
pack_int8(uint32_t * dst,const uint32_t * val)325 pack_int8(uint32_t *dst, const uint32_t *val)
326 {
327    *dst = (val[0] & 0xff) |
328           (val[1] & 0xff) << 8 |
329           (val[2] & 0xff) << 16 |
330           (val[3] & 0xff) << 24;
331 }
332 
333 static inline void
pack_int10_2(uint32_t * dst,const uint32_t * val)334 pack_int10_2(uint32_t *dst, const uint32_t *val)
335 {
336    *dst = (val[0] & 0x3ff) |
337           (val[1] & 0x3ff) << 10 |
338           (val[2] & 0x3ff) << 20 |
339           (val[3] & 0x3)   << 30;
340 }
341 
342 static inline void
pack_int16(uint32_t * dst,const uint32_t * val)343 pack_int16(uint32_t *dst, const uint32_t *val)
344 {
345    dst[0] = (val[0] & 0xffff) |
346             (val[1] & 0xffff) << 16;
347    dst[1] = (val[2] & 0xffff) |
348             (val[3] & 0xffff) << 16;
349 }
350 
351 static inline void
tu6_pack_border_color(struct bcolor_entry * bcolor,const VkClearColorValue * val,bool is_int)352 tu6_pack_border_color(struct bcolor_entry *bcolor, const VkClearColorValue *val, bool is_int)
353 {
354    memcpy(bcolor->fp32, val, 4 * sizeof(float));
355    if (is_int) {
356       pack_int16((uint32_t*) &bcolor->fp16, val->uint32);
357       return;
358    }
359 #define PACK_F(x, type) util_format_##type##_pack_rgba_float \
360    ( (uint8_t*) (&bcolor->x), 0, val->float32, 0, 1, 1)
361    PACK_F(ui16, r16g16b16a16_unorm);
362    PACK_F(si16, r16g16b16a16_snorm);
363    PACK_F(fp16, r16g16b16a16_float);
364    PACK_F(rgb565, r5g6b5_unorm);
365    PACK_F(rgb5a1, r5g5b5a1_unorm);
366    PACK_F(rgba4, r4g4b4a4_unorm);
367    PACK_F(ui8, r8g8b8a8_unorm);
368    PACK_F(si8, r8g8b8a8_snorm);
369    PACK_F(rgb10a2, r10g10b10a2_unorm);
370    util_format_z24x8_unorm_pack_z_float((uint8_t*) &bcolor->z24,
371                                         0, val->float32, 0, 1, 1);
372    PACK_F(srgb, r16g16b16a16_float); /* TODO: clamp? */
373 #undef PACK_F
374 }
375 
376 void
377 tu_dbg_log_gmem_load_store_skips(struct tu_device *device);
378 
379 #define perf_debug(device, fmt, ...) do {                               \
380    if (unlikely((device)->instance->debug_flags & TU_DEBUG_PERF))       \
381       mesa_log(MESA_LOG_WARN, (MESA_LOG_TAG), (fmt), ##__VA_ARGS__);    \
382 } while(0)
383 
384 #endif /* TU_UTIL_H */
385