17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2020 Valve Corporation
37ec681f3Smrg * SPDX-License-Identifier: MIT
47ec681f3Smrg *
57ec681f3Smrg * Authors:
67ec681f3Smrg *    Jonathan Marek <jonathan@marek.ca>
77ec681f3Smrg */
87ec681f3Smrg
9361fc4cbSmaya#ifndef TU_UTIL_H
10361fc4cbSmaya#define TU_UTIL_H
11361fc4cbSmaya
127ec681f3Smrg#include <assert.h>
137ec681f3Smrg#include <stdint.h>
147ec681f3Smrg
157ec681f3Smrg#include "util/macros.h"
167ec681f3Smrg#include "util/u_math.h"
177ec681f3Smrg#include "util/format/u_format_pack.h"
187ec681f3Smrg#include "util/format/u_format_zs.h"
197ec681f3Smrg#include "compiler/shader_enums.h"
207ec681f3Smrg
217ec681f3Smrg#include "adreno_common.xml.h"
227ec681f3Smrg#include "adreno_pm4.xml.h"
237ec681f3Smrg#include "a6xx.xml.h"
247ec681f3Smrg
257ec681f3Smrg#include <vulkan/vulkan.h>
267ec681f3Smrg#include "vk_util.h"
277ec681f3Smrg
287ec681f3Smrg#define TU_STAGE_MASK ((1 << MESA_SHADER_STAGES) - 1)
297ec681f3Smrg
307ec681f3Smrg#define tu_foreach_stage(stage, stage_bits)                                  \
317ec681f3Smrg   for (gl_shader_stage stage,                                               \
327ec681f3Smrg        __tmp = (gl_shader_stage)((stage_bits) &TU_STAGE_MASK);              \
337ec681f3Smrg        stage = __builtin_ffs(__tmp) - 1, __tmp; __tmp &= ~(1 << (stage)))
347ec681f3Smrg
357ec681f3Smrgstatic inline enum a3xx_msaa_samples
367ec681f3Smrgtu_msaa_samples(uint32_t samples)
377ec681f3Smrg{
387ec681f3Smrg   assert(__builtin_popcount(samples) == 1);
397ec681f3Smrg   return util_logbase2(samples);
407ec681f3Smrg}
417ec681f3Smrg
427ec681f3Smrgstatic inline uint32_t
437ec681f3Smrgtu6_stage2opcode(gl_shader_stage stage)
447ec681f3Smrg{
457ec681f3Smrg   if (stage == MESA_SHADER_FRAGMENT || stage == MESA_SHADER_COMPUTE)
467ec681f3Smrg      return CP_LOAD_STATE6_FRAG;
477ec681f3Smrg   return CP_LOAD_STATE6_GEOM;
487ec681f3Smrg}
497ec681f3Smrg
507ec681f3Smrgstatic inline enum a6xx_state_block
517ec681f3Smrgtu6_stage2texsb(gl_shader_stage stage)
527ec681f3Smrg{
537ec681f3Smrg   return SB6_VS_TEX + stage;
547ec681f3Smrg}
557ec681f3Smrg
567ec681f3Smrgstatic inline enum a6xx_state_block
577ec681f3Smrgtu6_stage2shadersb(gl_shader_stage stage)
587ec681f3Smrg{
597ec681f3Smrg   return SB6_VS_SHADER + stage;
607ec681f3Smrg}
617ec681f3Smrg
627ec681f3Smrgstatic inline enum a3xx_rop_code
637ec681f3Smrgtu6_rop(VkLogicOp op)
647ec681f3Smrg{
657ec681f3Smrg   /* note: hw enum matches the VK enum, but with the 4 bits reversed */
667ec681f3Smrg   static const uint8_t lookup[] = {
677ec681f3Smrg      [VK_LOGIC_OP_CLEAR]           = ROP_CLEAR,
687ec681f3Smrg      [VK_LOGIC_OP_AND]             = ROP_AND,
697ec681f3Smrg      [VK_LOGIC_OP_AND_REVERSE]     = ROP_AND_REVERSE,
707ec681f3Smrg      [VK_LOGIC_OP_COPY]            = ROP_COPY,
717ec681f3Smrg      [VK_LOGIC_OP_AND_INVERTED]    = ROP_AND_INVERTED,
727ec681f3Smrg      [VK_LOGIC_OP_NO_OP]           = ROP_NOOP,
737ec681f3Smrg      [VK_LOGIC_OP_XOR]             = ROP_XOR,
747ec681f3Smrg      [VK_LOGIC_OP_OR]              = ROP_OR,
757ec681f3Smrg      [VK_LOGIC_OP_NOR]             = ROP_NOR,
767ec681f3Smrg      [VK_LOGIC_OP_EQUIVALENT]      = ROP_EQUIV,
777ec681f3Smrg      [VK_LOGIC_OP_INVERT]          = ROP_INVERT,
787ec681f3Smrg      [VK_LOGIC_OP_OR_REVERSE]      = ROP_OR_REVERSE,
797ec681f3Smrg      [VK_LOGIC_OP_COPY_INVERTED]   = ROP_COPY_INVERTED,
807ec681f3Smrg      [VK_LOGIC_OP_OR_INVERTED]     = ROP_OR_INVERTED,
817ec681f3Smrg      [VK_LOGIC_OP_NAND]            = ROP_NAND,
827ec681f3Smrg      [VK_LOGIC_OP_SET]             = ROP_SET,
837ec681f3Smrg   };
847ec681f3Smrg   assert(op < ARRAY_SIZE(lookup));
857ec681f3Smrg   return lookup[op];
867ec681f3Smrg}
877ec681f3Smrg
887ec681f3Smrgstatic inline bool
897ec681f3Smrgtu6_primtype_line(enum pc_di_primtype type)
907ec681f3Smrg{
917ec681f3Smrg    switch(type) {
927ec681f3Smrg    case DI_PT_LINELIST:
937ec681f3Smrg    case DI_PT_LINESTRIP:
947ec681f3Smrg    case DI_PT_LINE_ADJ:
957ec681f3Smrg    case DI_PT_LINESTRIP_ADJ:
967ec681f3Smrg       return true;
977ec681f3Smrg    default:
987ec681f3Smrg       return false;
997ec681f3Smrg    }
1007ec681f3Smrg}
1017ec681f3Smrg
1027ec681f3Smrgstatic inline enum pc_di_primtype
1037ec681f3Smrgtu6_primtype(VkPrimitiveTopology topology)
1047ec681f3Smrg{
1057ec681f3Smrg   static const uint8_t lookup[] = {
1067ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_POINT_LIST]                    = DI_PT_POINTLIST,
1077ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_LINE_LIST]                     = DI_PT_LINELIST,
1087ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP]                    = DI_PT_LINESTRIP,
1097ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST]                 = DI_PT_TRILIST,
1107ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP]                = DI_PT_TRISTRIP,
1117ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN]                  = DI_PT_TRIFAN,
1127ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY]      = DI_PT_LINE_ADJ,
1137ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY]     = DI_PT_LINESTRIP_ADJ,
1147ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY]  = DI_PT_TRI_ADJ,
1157ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY] = DI_PT_TRISTRIP_ADJ,
1167ec681f3Smrg      /* Return PATCH0 and update in tu_pipeline_builder_parse_tessellation */
1177ec681f3Smrg      [VK_PRIMITIVE_TOPOLOGY_PATCH_LIST]                    = DI_PT_PATCHES0,
1187ec681f3Smrg   };
1197ec681f3Smrg   assert(topology < ARRAY_SIZE(lookup));
1207ec681f3Smrg   return lookup[topology];
1217ec681f3Smrg}
1227ec681f3Smrg
1237ec681f3Smrgstatic inline enum adreno_compare_func
1247ec681f3Smrgtu6_compare_func(VkCompareOp op)
1257ec681f3Smrg{
1267ec681f3Smrg   return (enum adreno_compare_func) op;
1277ec681f3Smrg}
1287ec681f3Smrg
1297ec681f3Smrgstatic inline enum adreno_stencil_op
1307ec681f3Smrgtu6_stencil_op(VkStencilOp op)
1317ec681f3Smrg{
1327ec681f3Smrg   return (enum adreno_stencil_op) op;
1337ec681f3Smrg}
1347ec681f3Smrg
1357ec681f3Smrgstatic inline enum adreno_rb_blend_factor
1367ec681f3Smrgtu6_blend_factor(VkBlendFactor factor)
1377ec681f3Smrg{
1387ec681f3Smrg   static const uint8_t lookup[] = {
1397ec681f3Smrg      [VK_BLEND_FACTOR_ZERO]                    = FACTOR_ZERO,
1407ec681f3Smrg      [VK_BLEND_FACTOR_ONE]                     = FACTOR_ONE,
1417ec681f3Smrg      [VK_BLEND_FACTOR_SRC_COLOR]               = FACTOR_SRC_COLOR,
1427ec681f3Smrg      [VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR]     = FACTOR_ONE_MINUS_SRC_COLOR,
1437ec681f3Smrg      [VK_BLEND_FACTOR_DST_COLOR]               = FACTOR_DST_COLOR,
1447ec681f3Smrg      [VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR]     = FACTOR_ONE_MINUS_DST_COLOR,
1457ec681f3Smrg      [VK_BLEND_FACTOR_SRC_ALPHA]               = FACTOR_SRC_ALPHA,
1467ec681f3Smrg      [VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA]     = FACTOR_ONE_MINUS_SRC_ALPHA,
1477ec681f3Smrg      [VK_BLEND_FACTOR_DST_ALPHA]               = FACTOR_DST_ALPHA,
1487ec681f3Smrg      [VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA]     = FACTOR_ONE_MINUS_DST_ALPHA,
1497ec681f3Smrg      [VK_BLEND_FACTOR_CONSTANT_COLOR]          = FACTOR_CONSTANT_COLOR,
1507ec681f3Smrg      [VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR]= FACTOR_ONE_MINUS_CONSTANT_COLOR,
1517ec681f3Smrg      [VK_BLEND_FACTOR_CONSTANT_ALPHA]          = FACTOR_CONSTANT_ALPHA,
1527ec681f3Smrg      [VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA]= FACTOR_ONE_MINUS_CONSTANT_ALPHA,
1537ec681f3Smrg      [VK_BLEND_FACTOR_SRC_ALPHA_SATURATE]      = FACTOR_SRC_ALPHA_SATURATE,
1547ec681f3Smrg      [VK_BLEND_FACTOR_SRC1_COLOR]              = FACTOR_SRC1_COLOR,
1557ec681f3Smrg      [VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR]    = FACTOR_ONE_MINUS_SRC1_COLOR,
1567ec681f3Smrg      [VK_BLEND_FACTOR_SRC1_ALPHA]              = FACTOR_SRC1_ALPHA,
1577ec681f3Smrg      [VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA]    = FACTOR_ONE_MINUS_SRC1_ALPHA,
1587ec681f3Smrg   };
1597ec681f3Smrg   assert(factor < ARRAY_SIZE(lookup));
1607ec681f3Smrg   return lookup[factor];
1617ec681f3Smrg}
1627ec681f3Smrg
1637ec681f3Smrgstatic inline enum a3xx_rb_blend_opcode
1647ec681f3Smrgtu6_blend_op(VkBlendOp op)
1657ec681f3Smrg{
1667ec681f3Smrg   return (enum a3xx_rb_blend_opcode) op;
1677ec681f3Smrg}
1687ec681f3Smrg
1697ec681f3Smrgstatic inline enum a6xx_tex_type
1707ec681f3Smrgtu6_tex_type(VkImageViewType type, bool storage)
1717ec681f3Smrg{
1727ec681f3Smrg   switch (type) {
1737ec681f3Smrg   default:
1747ec681f3Smrg   case VK_IMAGE_VIEW_TYPE_1D:
1757ec681f3Smrg   case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1767ec681f3Smrg      return A6XX_TEX_1D;
1777ec681f3Smrg   case VK_IMAGE_VIEW_TYPE_2D:
1787ec681f3Smrg   case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1797ec681f3Smrg      return A6XX_TEX_2D;
1807ec681f3Smrg   case VK_IMAGE_VIEW_TYPE_3D:
1817ec681f3Smrg      return A6XX_TEX_3D;
1827ec681f3Smrg   case VK_IMAGE_VIEW_TYPE_CUBE:
1837ec681f3Smrg   case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1847ec681f3Smrg      return storage ? A6XX_TEX_2D : A6XX_TEX_CUBE;
1857ec681f3Smrg   }
1867ec681f3Smrg}
1877ec681f3Smrg
1887ec681f3Smrgstatic inline enum a6xx_tex_clamp
1897ec681f3Smrgtu6_tex_wrap(VkSamplerAddressMode address_mode)
1907ec681f3Smrg{
1917ec681f3Smrg   uint8_t lookup[] = {
1927ec681f3Smrg      [VK_SAMPLER_ADDRESS_MODE_REPEAT]                = A6XX_TEX_REPEAT,
1937ec681f3Smrg      [VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT]       = A6XX_TEX_MIRROR_REPEAT,
1947ec681f3Smrg      [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE]         = A6XX_TEX_CLAMP_TO_EDGE,
1957ec681f3Smrg      [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER]       = A6XX_TEX_CLAMP_TO_BORDER,
1967ec681f3Smrg      [VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE]  = A6XX_TEX_MIRROR_CLAMP,
1977ec681f3Smrg   };
1987ec681f3Smrg   assert(address_mode < ARRAY_SIZE(lookup));
1997ec681f3Smrg   return lookup[address_mode];
2007ec681f3Smrg}
2017ec681f3Smrg
2027ec681f3Smrgstatic inline enum a6xx_tex_filter
2037ec681f3Smrgtu6_tex_filter(VkFilter filter, unsigned aniso)
2047ec681f3Smrg{
2057ec681f3Smrg   switch (filter) {
2067ec681f3Smrg   case VK_FILTER_NEAREST:
2077ec681f3Smrg      return A6XX_TEX_NEAREST;
2087ec681f3Smrg   case VK_FILTER_LINEAR:
2097ec681f3Smrg      return aniso ? A6XX_TEX_ANISO : A6XX_TEX_LINEAR;
2107ec681f3Smrg   case VK_FILTER_CUBIC_EXT:
2117ec681f3Smrg      return A6XX_TEX_CUBIC;
2127ec681f3Smrg   default:
2137ec681f3Smrg      unreachable("illegal texture filter");
2147ec681f3Smrg      break;
2157ec681f3Smrg   }
2167ec681f3Smrg}
2177ec681f3Smrg
2187ec681f3Smrgstatic inline enum a6xx_reduction_mode
2197ec681f3Smrgtu6_reduction_mode(VkSamplerReductionMode reduction_mode)
2207ec681f3Smrg{
2217ec681f3Smrg   return (enum a6xx_reduction_mode) reduction_mode;
2227ec681f3Smrg}
2237ec681f3Smrg
2247ec681f3Smrgstatic inline enum a6xx_depth_format
2257ec681f3Smrgtu6_pipe2depth(VkFormat format)
2267ec681f3Smrg{
2277ec681f3Smrg   switch (format) {
2287ec681f3Smrg   case VK_FORMAT_D16_UNORM:
2297ec681f3Smrg      return DEPTH6_16;
2307ec681f3Smrg   case VK_FORMAT_X8_D24_UNORM_PACK32:
2317ec681f3Smrg   case VK_FORMAT_D24_UNORM_S8_UINT:
2327ec681f3Smrg      return DEPTH6_24_8;
2337ec681f3Smrg   case VK_FORMAT_D32_SFLOAT:
2347ec681f3Smrg   case VK_FORMAT_D32_SFLOAT_S8_UINT:
2357ec681f3Smrg   case VK_FORMAT_S8_UINT:
2367ec681f3Smrg      return DEPTH6_32;
2377ec681f3Smrg   default:
2387ec681f3Smrg      return ~0;
2397ec681f3Smrg   }
2407ec681f3Smrg}
2417ec681f3Smrg
2427ec681f3Smrgstatic inline enum a6xx_polygon_mode
2437ec681f3Smrgtu6_polygon_mode(VkPolygonMode mode)
2447ec681f3Smrg{
2457ec681f3Smrg   switch (mode) {
2467ec681f3Smrg   case VK_POLYGON_MODE_POINT:
2477ec681f3Smrg      return POLYMODE6_POINTS;
2487ec681f3Smrg   case VK_POLYGON_MODE_LINE:
2497ec681f3Smrg      return POLYMODE6_LINES;
2507ec681f3Smrg   case VK_POLYGON_MODE_FILL:
2517ec681f3Smrg      return POLYMODE6_TRIANGLES;
2527ec681f3Smrg   default:
2537ec681f3Smrg      unreachable("bad polygon mode");
2547ec681f3Smrg   }
2557ec681f3Smrg}
2567ec681f3Smrg
2577ec681f3Smrgstruct bcolor_entry {
2587ec681f3Smrg   uint32_t fp32[4];
2597ec681f3Smrg   uint64_t ui16;
2607ec681f3Smrg   uint64_t si16;
2617ec681f3Smrg   uint64_t fp16;
2627ec681f3Smrg   uint16_t rgb565;
2637ec681f3Smrg   uint16_t rgb5a1;
2647ec681f3Smrg   uint16_t rgba4;
2657ec681f3Smrg   uint8_t __pad0[2];
2667ec681f3Smrg   uint32_t ui8;
2677ec681f3Smrg   uint32_t si8;
2687ec681f3Smrg   uint32_t rgb10a2;
2697ec681f3Smrg   uint32_t z24; /* also s8? */
2707ec681f3Smrg   uint64_t srgb;
2717ec681f3Smrg   uint8_t  __pad1[56];
2727ec681f3Smrg} __attribute__((aligned(128)));
2737ec681f3Smrg
2747ec681f3Smrg/* vulkan does not want clamping of integer clear values, differs from u_format
2757ec681f3Smrg * see spec for VkClearColorValue
2767ec681f3Smrg */
2777ec681f3Smrgstatic inline void
2787ec681f3Smrgpack_int8(uint32_t *dst, const uint32_t *val)
2797ec681f3Smrg{
2807ec681f3Smrg   *dst = (val[0] & 0xff) |
2817ec681f3Smrg          (val[1] & 0xff) << 8 |
2827ec681f3Smrg          (val[2] & 0xff) << 16 |
2837ec681f3Smrg          (val[3] & 0xff) << 24;
2847ec681f3Smrg}
2857ec681f3Smrg
2867ec681f3Smrgstatic inline void
2877ec681f3Smrgpack_int10_2(uint32_t *dst, const uint32_t *val)
2887ec681f3Smrg{
2897ec681f3Smrg   *dst = (val[0] & 0x3ff) |
2907ec681f3Smrg          (val[1] & 0x3ff) << 10 |
2917ec681f3Smrg          (val[2] & 0x3ff) << 20 |
2927ec681f3Smrg          (val[3] & 0x3)   << 30;
2937ec681f3Smrg}
2947ec681f3Smrg
2957ec681f3Smrgstatic inline void
2967ec681f3Smrgpack_int16(uint32_t *dst, const uint32_t *val)
2977ec681f3Smrg{
2987ec681f3Smrg   dst[0] = (val[0] & 0xffff) |
2997ec681f3Smrg            (val[1] & 0xffff) << 16;
3007ec681f3Smrg   dst[1] = (val[2] & 0xffff) |
3017ec681f3Smrg            (val[3] & 0xffff) << 16;
3027ec681f3Smrg}
3037ec681f3Smrg
3047ec681f3Smrgstatic inline void
3057ec681f3Smrgtu6_pack_border_color(struct bcolor_entry *bcolor, const VkClearColorValue *val, bool is_int)
3067ec681f3Smrg{
3077ec681f3Smrg   memcpy(bcolor->fp32, val, 4 * sizeof(float));
3087ec681f3Smrg   if (is_int) {
3097ec681f3Smrg      pack_int16((uint32_t*) &bcolor->fp16, val->uint32);
3107ec681f3Smrg      return;
3117ec681f3Smrg   }
3127ec681f3Smrg#define PACK_F(x, type) util_format_##type##_pack_rgba_float \
3137ec681f3Smrg   ( (uint8_t*) (&bcolor->x), 0, val->float32, 0, 1, 1)
3147ec681f3Smrg   PACK_F(ui16, r16g16b16a16_unorm);
3157ec681f3Smrg   PACK_F(si16, r16g16b16a16_snorm);
3167ec681f3Smrg   PACK_F(fp16, r16g16b16a16_float);
3177ec681f3Smrg   PACK_F(rgb565, r5g6b5_unorm);
3187ec681f3Smrg   PACK_F(rgb5a1, r5g5b5a1_unorm);
3197ec681f3Smrg   PACK_F(rgba4, r4g4b4a4_unorm);
3207ec681f3Smrg   PACK_F(ui8, r8g8b8a8_unorm);
3217ec681f3Smrg   PACK_F(si8, r8g8b8a8_snorm);
3227ec681f3Smrg   PACK_F(rgb10a2, r10g10b10a2_unorm);
3237ec681f3Smrg   util_format_x8z24_unorm_pack_z_float((uint8_t*) &bcolor->z24,
3247ec681f3Smrg                                        0, val->float32, 0, 1, 1);
3257ec681f3Smrg   PACK_F(srgb, r16g16b16a16_float); /* TODO: clamp? */
3267ec681f3Smrg#undef PACK_F
3277ec681f3Smrg}
328361fc4cbSmaya
329361fc4cbSmaya#endif /* TU_UTIL_H */
330