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 <assert.h>
13 #include <stdint.h>
14 
15 #include "util/macros.h"
16 #include "util/u_math.h"
17 #include "util/format/u_format_pack.h"
18 #include "util/format/u_format_zs.h"
19 #include "compiler/shader_enums.h"
20 
21 #include "adreno_common.xml.h"
22 #include "adreno_pm4.xml.h"
23 #include "a6xx.xml.h"
24 
25 #include <vulkan/vulkan.h>
26 #include "vk_util.h"
27 
28 #define TU_STAGE_MASK ((1 << MESA_SHADER_STAGES) - 1)
29 
30 #define tu_foreach_stage(stage, stage_bits)                                  \
31    for (gl_shader_stage stage,                                               \
32         __tmp = (gl_shader_stage)((stage_bits) &TU_STAGE_MASK);              \
33         stage = __builtin_ffs(__tmp) - 1, __tmp; __tmp &= ~(1 << (stage)))
34 
35 static inline enum a3xx_msaa_samples
tu_msaa_samples(uint32_t samples)36 tu_msaa_samples(uint32_t samples)
37 {
38    assert(__builtin_popcount(samples) == 1);
39    return util_logbase2(samples);
40 }
41 
42 static inline uint32_t
tu6_stage2opcode(gl_shader_stage stage)43 tu6_stage2opcode(gl_shader_stage stage)
44 {
45    if (stage == MESA_SHADER_FRAGMENT || stage == MESA_SHADER_COMPUTE)
46       return CP_LOAD_STATE6_FRAG;
47    return CP_LOAD_STATE6_GEOM;
48 }
49 
50 static inline enum a6xx_state_block
tu6_stage2texsb(gl_shader_stage stage)51 tu6_stage2texsb(gl_shader_stage stage)
52 {
53    return SB6_VS_TEX + stage;
54 }
55 
56 static inline enum a6xx_state_block
tu6_stage2shadersb(gl_shader_stage stage)57 tu6_stage2shadersb(gl_shader_stage stage)
58 {
59    return SB6_VS_SHADER + stage;
60 }
61 
62 static inline enum a3xx_rop_code
tu6_rop(VkLogicOp op)63 tu6_rop(VkLogicOp op)
64 {
65    /* note: hw enum matches the VK enum, but with the 4 bits reversed */
66    static const uint8_t lookup[] = {
67       [VK_LOGIC_OP_CLEAR]           = ROP_CLEAR,
68       [VK_LOGIC_OP_AND]             = ROP_AND,
69       [VK_LOGIC_OP_AND_REVERSE]     = ROP_AND_REVERSE,
70       [VK_LOGIC_OP_COPY]            = ROP_COPY,
71       [VK_LOGIC_OP_AND_INVERTED]    = ROP_AND_INVERTED,
72       [VK_LOGIC_OP_NO_OP]           = ROP_NOOP,
73       [VK_LOGIC_OP_XOR]             = ROP_XOR,
74       [VK_LOGIC_OP_OR]              = ROP_OR,
75       [VK_LOGIC_OP_NOR]             = ROP_NOR,
76       [VK_LOGIC_OP_EQUIVALENT]      = ROP_EQUIV,
77       [VK_LOGIC_OP_INVERT]          = ROP_INVERT,
78       [VK_LOGIC_OP_OR_REVERSE]      = ROP_OR_REVERSE,
79       [VK_LOGIC_OP_COPY_INVERTED]   = ROP_COPY_INVERTED,
80       [VK_LOGIC_OP_OR_INVERTED]     = ROP_OR_INVERTED,
81       [VK_LOGIC_OP_NAND]            = ROP_NAND,
82       [VK_LOGIC_OP_SET]             = ROP_SET,
83    };
84    assert(op < ARRAY_SIZE(lookup));
85    return lookup[op];
86 }
87 
88 static inline bool
tu6_primtype_line(enum pc_di_primtype type)89 tu6_primtype_line(enum pc_di_primtype type)
90 {
91     switch(type) {
92     case DI_PT_LINELIST:
93     case DI_PT_LINESTRIP:
94     case DI_PT_LINE_ADJ:
95     case DI_PT_LINESTRIP_ADJ:
96        return true;
97     default:
98        return false;
99     }
100 }
101 
102 static inline enum pc_di_primtype
tu6_primtype(VkPrimitiveTopology topology)103 tu6_primtype(VkPrimitiveTopology topology)
104 {
105    static const uint8_t lookup[] = {
106       [VK_PRIMITIVE_TOPOLOGY_POINT_LIST]                    = DI_PT_POINTLIST,
107       [VK_PRIMITIVE_TOPOLOGY_LINE_LIST]                     = DI_PT_LINELIST,
108       [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP]                    = DI_PT_LINESTRIP,
109       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST]                 = DI_PT_TRILIST,
110       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP]                = DI_PT_TRISTRIP,
111       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN]                  = DI_PT_TRIFAN,
112       [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY]      = DI_PT_LINE_ADJ,
113       [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY]     = DI_PT_LINESTRIP_ADJ,
114       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY]  = DI_PT_TRI_ADJ,
115       [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY] = DI_PT_TRISTRIP_ADJ,
116       /* Return PATCH0 and update in tu_pipeline_builder_parse_tessellation */
117       [VK_PRIMITIVE_TOPOLOGY_PATCH_LIST]                    = DI_PT_PATCHES0,
118    };
119    assert(topology < ARRAY_SIZE(lookup));
120    return lookup[topology];
121 }
122 
123 static inline enum adreno_compare_func
tu6_compare_func(VkCompareOp op)124 tu6_compare_func(VkCompareOp op)
125 {
126    return (enum adreno_compare_func) op;
127 }
128 
129 static inline enum adreno_stencil_op
tu6_stencil_op(VkStencilOp op)130 tu6_stencil_op(VkStencilOp op)
131 {
132    return (enum adreno_stencil_op) op;
133 }
134 
135 static inline enum adreno_rb_blend_factor
tu6_blend_factor(VkBlendFactor factor)136 tu6_blend_factor(VkBlendFactor factor)
137 {
138    static const uint8_t lookup[] = {
139       [VK_BLEND_FACTOR_ZERO]                    = FACTOR_ZERO,
140       [VK_BLEND_FACTOR_ONE]                     = FACTOR_ONE,
141       [VK_BLEND_FACTOR_SRC_COLOR]               = FACTOR_SRC_COLOR,
142       [VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR]     = FACTOR_ONE_MINUS_SRC_COLOR,
143       [VK_BLEND_FACTOR_DST_COLOR]               = FACTOR_DST_COLOR,
144       [VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR]     = FACTOR_ONE_MINUS_DST_COLOR,
145       [VK_BLEND_FACTOR_SRC_ALPHA]               = FACTOR_SRC_ALPHA,
146       [VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA]     = FACTOR_ONE_MINUS_SRC_ALPHA,
147       [VK_BLEND_FACTOR_DST_ALPHA]               = FACTOR_DST_ALPHA,
148       [VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA]     = FACTOR_ONE_MINUS_DST_ALPHA,
149       [VK_BLEND_FACTOR_CONSTANT_COLOR]          = FACTOR_CONSTANT_COLOR,
150       [VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR]= FACTOR_ONE_MINUS_CONSTANT_COLOR,
151       [VK_BLEND_FACTOR_CONSTANT_ALPHA]          = FACTOR_CONSTANT_ALPHA,
152       [VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA]= FACTOR_ONE_MINUS_CONSTANT_ALPHA,
153       [VK_BLEND_FACTOR_SRC_ALPHA_SATURATE]      = FACTOR_SRC_ALPHA_SATURATE,
154       [VK_BLEND_FACTOR_SRC1_COLOR]              = FACTOR_SRC1_COLOR,
155       [VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR]    = FACTOR_ONE_MINUS_SRC1_COLOR,
156       [VK_BLEND_FACTOR_SRC1_ALPHA]              = FACTOR_SRC1_ALPHA,
157       [VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA]    = FACTOR_ONE_MINUS_SRC1_ALPHA,
158    };
159    assert(factor < ARRAY_SIZE(lookup));
160    return lookup[factor];
161 }
162 
163 static inline enum a3xx_rb_blend_opcode
tu6_blend_op(VkBlendOp op)164 tu6_blend_op(VkBlendOp op)
165 {
166    return (enum a3xx_rb_blend_opcode) op;
167 }
168 
169 static inline enum a6xx_tex_type
tu6_tex_type(VkImageViewType type,bool storage)170 tu6_tex_type(VkImageViewType type, bool storage)
171 {
172    switch (type) {
173    default:
174    case VK_IMAGE_VIEW_TYPE_1D:
175    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
176       return A6XX_TEX_1D;
177    case VK_IMAGE_VIEW_TYPE_2D:
178    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
179       return A6XX_TEX_2D;
180    case VK_IMAGE_VIEW_TYPE_3D:
181       return A6XX_TEX_3D;
182    case VK_IMAGE_VIEW_TYPE_CUBE:
183    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
184       return storage ? A6XX_TEX_2D : A6XX_TEX_CUBE;
185    }
186 }
187 
188 static inline enum a6xx_tex_clamp
tu6_tex_wrap(VkSamplerAddressMode address_mode)189 tu6_tex_wrap(VkSamplerAddressMode address_mode)
190 {
191    uint8_t lookup[] = {
192       [VK_SAMPLER_ADDRESS_MODE_REPEAT]                = A6XX_TEX_REPEAT,
193       [VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT]       = A6XX_TEX_MIRROR_REPEAT,
194       [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE]         = A6XX_TEX_CLAMP_TO_EDGE,
195       [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER]       = A6XX_TEX_CLAMP_TO_BORDER,
196       [VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE]  = A6XX_TEX_MIRROR_CLAMP,
197    };
198    assert(address_mode < ARRAY_SIZE(lookup));
199    return lookup[address_mode];
200 }
201 
202 static inline enum a6xx_tex_filter
tu6_tex_filter(VkFilter filter,unsigned aniso)203 tu6_tex_filter(VkFilter filter, unsigned aniso)
204 {
205    switch (filter) {
206    case VK_FILTER_NEAREST:
207       return A6XX_TEX_NEAREST;
208    case VK_FILTER_LINEAR:
209       return aniso ? A6XX_TEX_ANISO : A6XX_TEX_LINEAR;
210    case VK_FILTER_CUBIC_EXT:
211       return A6XX_TEX_CUBIC;
212    default:
213       unreachable("illegal texture filter");
214       break;
215    }
216 }
217 
218 static inline enum a6xx_reduction_mode
tu6_reduction_mode(VkSamplerReductionMode reduction_mode)219 tu6_reduction_mode(VkSamplerReductionMode reduction_mode)
220 {
221    return (enum a6xx_reduction_mode) reduction_mode;
222 }
223 
224 static inline enum a6xx_depth_format
tu6_pipe2depth(VkFormat format)225 tu6_pipe2depth(VkFormat format)
226 {
227    switch (format) {
228    case VK_FORMAT_D16_UNORM:
229       return DEPTH6_16;
230    case VK_FORMAT_X8_D24_UNORM_PACK32:
231    case VK_FORMAT_D24_UNORM_S8_UINT:
232       return DEPTH6_24_8;
233    case VK_FORMAT_D32_SFLOAT:
234    case VK_FORMAT_D32_SFLOAT_S8_UINT:
235    case VK_FORMAT_S8_UINT:
236       return DEPTH6_32;
237    default:
238       return ~0;
239    }
240 }
241 
242 static inline enum a6xx_polygon_mode
tu6_polygon_mode(VkPolygonMode mode)243 tu6_polygon_mode(VkPolygonMode mode)
244 {
245    switch (mode) {
246    case VK_POLYGON_MODE_POINT:
247       return POLYMODE6_POINTS;
248    case VK_POLYGON_MODE_LINE:
249       return POLYMODE6_LINES;
250    case VK_POLYGON_MODE_FILL:
251       return POLYMODE6_TRIANGLES;
252    default:
253       unreachable("bad polygon mode");
254    }
255 }
256 
257 struct bcolor_entry {
258    uint32_t fp32[4];
259    uint64_t ui16;
260    uint64_t si16;
261    uint64_t fp16;
262    uint16_t rgb565;
263    uint16_t rgb5a1;
264    uint16_t rgba4;
265    uint8_t __pad0[2];
266    uint32_t ui8;
267    uint32_t si8;
268    uint32_t rgb10a2;
269    uint32_t z24; /* also s8? */
270    uint64_t srgb;
271    uint8_t  __pad1[56];
272 } __attribute__((aligned(128)));
273 
274 /* vulkan does not want clamping of integer clear values, differs from u_format
275  * see spec for VkClearColorValue
276  */
277 static inline void
pack_int8(uint32_t * dst,const uint32_t * val)278 pack_int8(uint32_t *dst, const uint32_t *val)
279 {
280    *dst = (val[0] & 0xff) |
281           (val[1] & 0xff) << 8 |
282           (val[2] & 0xff) << 16 |
283           (val[3] & 0xff) << 24;
284 }
285 
286 static inline void
pack_int10_2(uint32_t * dst,const uint32_t * val)287 pack_int10_2(uint32_t *dst, const uint32_t *val)
288 {
289    *dst = (val[0] & 0x3ff) |
290           (val[1] & 0x3ff) << 10 |
291           (val[2] & 0x3ff) << 20 |
292           (val[3] & 0x3)   << 30;
293 }
294 
295 static inline void
pack_int16(uint32_t * dst,const uint32_t * val)296 pack_int16(uint32_t *dst, const uint32_t *val)
297 {
298    dst[0] = (val[0] & 0xffff) |
299             (val[1] & 0xffff) << 16;
300    dst[1] = (val[2] & 0xffff) |
301             (val[3] & 0xffff) << 16;
302 }
303 
304 static inline void
tu6_pack_border_color(struct bcolor_entry * bcolor,const VkClearColorValue * val,bool is_int)305 tu6_pack_border_color(struct bcolor_entry *bcolor, const VkClearColorValue *val, bool is_int)
306 {
307    memcpy(bcolor->fp32, val, 4 * sizeof(float));
308    if (is_int) {
309       pack_int16((uint32_t*) &bcolor->fp16, val->uint32);
310       return;
311    }
312 #define PACK_F(x, type) util_format_##type##_pack_rgba_float \
313    ( (uint8_t*) (&bcolor->x), 0, val->float32, 0, 1, 1)
314    PACK_F(ui16, r16g16b16a16_unorm);
315    PACK_F(si16, r16g16b16a16_snorm);
316    PACK_F(fp16, r16g16b16a16_float);
317    PACK_F(rgb565, r5g6b5_unorm);
318    PACK_F(rgb5a1, r5g5b5a1_unorm);
319    PACK_F(rgba4, r4g4b4a4_unorm);
320    PACK_F(ui8, r8g8b8a8_unorm);
321    PACK_F(si8, r8g8b8a8_snorm);
322    PACK_F(rgb10a2, r10g10b10a2_unorm);
323    util_format_x8z24_unorm_pack_z_float((uint8_t*) &bcolor->z24,
324                                         0, val->float32, 0, 1, 1);
325    PACK_F(srgb, r16g16b16a16_float); /* TODO: clamp? */
326 #undef PACK_F
327 }
328 
329 #endif /* TU_UTIL_H */
330