• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Intel Corporation
3  * Copyright 2016 Broadcom
4  * Copyright 2020 Collabora, Ltd.
5  * Copyright 2024 Alyssa Rosenzweig
6  * SPDX-License-Identifier: MIT
7  */
8 
9 #pragma once
10 
11 #include "compiler/libcl/libcl.h"
12 #include "util/bitpack_helpers.h"
13 
14 #ifndef __OPENCL_VERSION__
15 #include <inttypes.h>
16 #include <stdio.h>
17 #include "util/half_float.h"
18 #endif
19 
20 #define __gen_unpack_float(x, y, z) uif(__gen_unpack_uint(x, y, z))
21 #define __gen_unpack_half(x, y, z)                                             \
22    _mesa_half_to_float(__gen_unpack_uint(x, y, z))
23 
24 static inline uint64_t
__gen_unpack_uint(CONST uint32_t * restrict cl,uint32_t start,uint32_t end)25 __gen_unpack_uint(CONST uint32_t *restrict cl, uint32_t start, uint32_t end)
26 {
27    uint64_t val = 0;
28    const int width = end - start + 1;
29    const uint64_t mask =
30       (width == 64) ? ~((uint64_t)0) : ((uint64_t)1 << width) - 1;
31 
32    for (unsigned word = start / 32; word < (end / 32) + 1; word++) {
33       val |= ((uint64_t)cl[word]) << ((word - start / 32) * 32);
34    }
35 
36    return (val >> (start % 32)) & mask;
37 }
38 
39 /*
40  * LODs are 4:6 fixed point. We must clamp before converting to integers to
41  * avoid undefined behaviour for out-of-bounds inputs like +/- infinity.
42  */
43 static inline uint32_t
__gen_pack_lod(float f,uint32_t start,uint32_t end)44 __gen_pack_lod(float f, uint32_t start, uint32_t end)
45 {
46    uint32_t fixed = CLAMP(f * (1 << 6), 0 /* 0.0 */, 0x380 /* 14.0 */);
47    return util_bitpack_uint(fixed, start, end);
48 }
49 
50 static inline float
__gen_unpack_lod(CONST uint32_t * restrict cl,uint32_t start,uint32_t end)51 __gen_unpack_lod(CONST uint32_t *restrict cl, uint32_t start, uint32_t end)
52 {
53    return ((float)__gen_unpack_uint(cl, start, end)) / (1 << 6);
54 }
55 
56 static inline uint64_t
__gen_unpack_sint(CONST uint32_t * restrict cl,uint32_t start,uint32_t end)57 __gen_unpack_sint(CONST uint32_t *restrict cl, uint32_t start, uint32_t end)
58 {
59    int size = end - start + 1;
60    int64_t val = __gen_unpack_uint(cl, start, end);
61 
62    return util_sign_extend(val, size);
63 }
64 
65 static inline uint64_t
__gen_to_groups(uint32_t value,uint32_t group_size,uint32_t length)66 __gen_to_groups(uint32_t value, uint32_t group_size, uint32_t length)
67 {
68    /* Zero is not representable, clamp to minimum */
69    if (value == 0)
70       return 1;
71 
72    /* Round up to the nearest number of groups */
73    uint32_t groups = DIV_ROUND_UP(value, group_size);
74 
75    /* The 0 encoding means "all" */
76    if (groups == ((uint64_t)1) << length)
77       return 0;
78 
79    /* Otherwise it's encoded as the identity */
80    assert(groups < (1u << length) && "out of bounds");
81    assert(groups >= 1 && "exhaustive");
82    return groups;
83 }
84 
85 static inline uint64_t
__gen_from_groups(uint32_t value,uint32_t group_size,uint32_t length)86 __gen_from_groups(uint32_t value, uint32_t group_size, uint32_t length)
87 {
88    return group_size * (value ? value : (1 << length));
89 }
90 
91 #define agx_pack(dst, T, name)                                                 \
92    for (struct AGX_##T name = {AGX_##T##_header},                              \
93                        *_loop_count = (GLOBAL void *)((uintptr_t)0);           \
94         (uintptr_t)_loop_count < 1; (                                          \
95            {                                                                   \
96               AGX_##T##_pack((GLOBAL uint32_t *)(dst), &name);                 \
97               _loop_count = (GLOBAL void *)(((uintptr_t)_loop_count) + 1);     \
98            }))
99 
100 #define agx_unpack(fp, src, T, name)                                           \
101    struct AGX_##T name;                                                        \
102    AGX_##T##_unpack(fp, (CONST uint8_t *)(src), &name)
103 
104 #define agx_print(fp, T, var, indent) AGX_##T##_print(fp, &(var), indent)
105 
106 static inline void
agx_merge_helper(uint32_t * dst,const uint32_t * src,size_t bytes)107 agx_merge_helper(uint32_t *dst, const uint32_t *src, size_t bytes)
108 {
109    assert((bytes & 3) == 0);
110 
111    for (unsigned i = 0; i < (bytes / 4); ++i)
112       dst[i] |= src[i];
113 }
114 
115 #define agx_merge(packed1, packed2, type)                                      \
116    agx_merge_helper((packed1).opaque, (packed2).opaque, AGX_##type##_LENGTH)
117 
118 #if defined(NDEBUG) || defined(__OPENCL_VERSION__)
119 #define agx_genxml_validate_bounds(a, b, c)
120 #define agx_genxml_validate_mask(a, b, c, d, e) true
121 #define agx_genxml_validate_exact(a, b, c, d)   true
122 #else
123 static inline void
agx_genxml_validate_bounds(const char * name,uint64_t value,uint64_t bound)124 agx_genxml_validate_bounds(const char *name, uint64_t value, uint64_t bound)
125 {
126    if (unlikely(value >= bound)) {
127       fprintf(stderr, "%s out-of-bounds, got 0x%" PRIx64 ", max %" PRIx64 "\n",
128               name, value, bound);
129 
130       unreachable("Out-of-bounds pack");
131    }
132 }
133 
134 static inline bool
agx_genxml_validate_mask(FILE * fp,const char * name,const void * cl_,uint32_t index,uint32_t bad_mask)135 agx_genxml_validate_mask(FILE *fp, const char *name, const void *cl_,
136                          uint32_t index, uint32_t bad_mask)
137 {
138    const uint32_t *cl = (const uint32_t *)cl_;
139    uint32_t bad = cl[index] & bad_mask;
140 
141    if (bad && fp != NULL) {
142       fprintf(
143          fp,
144          "XXX: Unknown field of %s unpacked at word %u got %X, bad mask %X\n",
145          name, index, cl[index], bad);
146    }
147 
148    return bad == 0;
149 }
150 
151 static bool
agx_genxml_validate_exact(FILE * fp,const char * name,uint64_t value,uint64_t exact)152 agx_genxml_validate_exact(FILE *fp, const char *name, uint64_t value,
153                           uint64_t exact)
154 {
155    if (value != exact && fp != NULL) {
156       fprintf(fp, "XXX: Expected %s to equal %" PRIx64 " but got %" PRIx64 "\n",
157               name, value, exact);
158    }
159 
160    return value == exact;
161 }
162 
163 #endif
164 
165 /* Everything after this is autogenerated from XML. Do not hand edit. */
166