1 /* 2 * Copyright 2020 Valve Corporation 3 * SPDX-License-Identifier: MIT 4 * 5 * Authors: 6 * Jonathan Marek <jonathan (at) 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 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 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 51 tu6_stage2texsb(gl_shader_stage stage) 52 { 53 return SB6_VS_TEX + stage; 54 } 55 56 static inline enum a6xx_state_block 57 tu6_stage2shadersb(gl_shader_stage stage) 58 { 59 return SB6_VS_SHADER + stage; 60 } 61 62 static inline enum a3xx_rop_code 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 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 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 124 tu6_compare_func(VkCompareOp op) 125 { 126 return (enum adreno_compare_func) op; 127 } 128 129 static inline enum adreno_stencil_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 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 164 tu6_blend_op(VkBlendOp op) 165 { 166 return (enum a3xx_rb_blend_opcode) op; 167 } 168 169 static inline enum a6xx_tex_type 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 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 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 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 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 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 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 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 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 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