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 26VkResult 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 43void 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 64void 65tu_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 76static inline enum a3xx_msaa_samples 77tu_msaa_samples(uint32_t samples) 78{ 79 assert(__builtin_popcount(samples) == 1); 80 return util_logbase2(samples); 81} 82 83static inline uint32_t 84tu6_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 91static inline enum a6xx_state_block 92tu6_stage2texsb(gl_shader_stage stage) 93{ 94 return SB6_VS_TEX + stage; 95} 96 97static inline enum a6xx_state_block 98tu6_stage2shadersb(gl_shader_stage stage) 99{ 100 return SB6_VS_SHADER + stage; 101} 102 103static inline enum a3xx_rop_code 104tu6_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 129static inline bool 130tu6_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 143static inline bool 144tu6_primtype_patches(enum pc_di_primtype type) 145{ 146 return type >= DI_PT_PATCHES0 && type <= DI_PT_PATCHES31; 147} 148 149static inline enum pc_di_primtype 150tu6_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 170static inline enum adreno_compare_func 171tu6_compare_func(VkCompareOp op) 172{ 173 return (enum adreno_compare_func) op; 174} 175 176static inline enum adreno_stencil_op 177tu6_stencil_op(VkStencilOp op) 178{ 179 return (enum adreno_stencil_op) op; 180} 181 182static inline enum adreno_rb_blend_factor 183tu6_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 210static inline enum a3xx_rb_blend_opcode 211tu6_blend_op(VkBlendOp op) 212{ 213 return (enum a3xx_rb_blend_opcode) op; 214} 215 216static inline enum a6xx_tex_type 217tu6_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 235static inline enum a6xx_tex_clamp 236tu6_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 249static inline enum a6xx_tex_filter 250tu6_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 265static inline enum a6xx_reduction_mode 266tu6_reduction_mode(VkSamplerReductionMode reduction_mode) 267{ 268 return (enum a6xx_reduction_mode) reduction_mode; 269} 270 271static inline enum a6xx_depth_format 272tu6_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 289static inline enum a6xx_polygon_mode 290tu6_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 304struct 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 */ 324static inline void 325pack_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 333static inline void 334pack_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 342static inline void 343pack_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 351static inline void 352tu6_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 376void 377tu_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