yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
6.1 KiB192 linesraw
1#ifndef SLANG_CORE_BYTE_ENCODE_UTIL_H
2#define SLANG_CORE_BYTE_ENCODE_UTIL_H
3
4#include "slang-list.h"
5
6namespace Slang
7{
8
9struct ByteEncodeUtil
10{
11    enum
12    {
13        kMaxLiteEncodeUInt16 = 3, /// One byte for prefix, the remaining 2 bytes hold the value
14        kMaxLiteEncodeUInt32 = 5, /// One byte for prefix, the remaining 4 bytes hold the value
15        // Cut values for 'Lite' encoding style
16        kLiteCut1 = 185,
17        kLiteCut2 = 249,
18    };
19
20    /** Find the most significant bit for 8 bits
21    @param v The value to find most significant bit on
22    @return The most significant bit, or -1 if no bits are set
23    */
24    SLANG_FORCE_INLINE static int calcMsb8(uint32_t v);
25
26    /** Find the most significant bit for 32 bits
27    @param v The value to find most significant bit on
28    @return The most significant bit, or -1 if no bits are set
29    */
30    SLANG_FORCE_INLINE static int calcMsb32(uint32_t v);
31
32    /** Calculates the 'most significant' byte ie the highest bytes that is non zero.
33     Note return value is *undefined* if in is 0.
34     @param in Value - cannot be 0.
35     @return The byte index of the highest byte that is non zero.
36     */
37    SLANG_FORCE_INLINE static int calcNonZeroMsByte32(uint32_t in);
38
39    /** Calculates the 'most significant' byte ie the highest bytes that is non zero.
40    @param in Value - cannot be 0.
41    @return The byte index of the highest byte that is non zero.
42    */
43    SLANG_FORCE_INLINE static int calcMsByte32(uint32_t in);
44
45    /// Calculate the size of encoding bytes
46    static size_t calcEncodeLiteSizeUInt32(const uint32_t* in, size_t num);
47
48    /// Calculate the size of a single value
49    static size_t calcEncodeLiteSizeUInt32(uint32_t in);
50
51    /** Encodes a uint32_t as an integer
52     @return the number of bytes needed to encode */
53    static int encodeLiteUInt32(uint32_t in, uint8_t out[kMaxLiteEncodeUInt32]);
54
55    /** Decode a lite encoding.
56     @param in The lite encoded bytes
57     @param out Value constructed
58    @return number of bytes on in consumed */
59    static int decodeLiteUInt32(const uint8_t* in, uint32_t* out);
60
61    /** Encode an array of uint32_t
62    @param in The values to encode
63    @param num The amount of values to encode
64    @param encodeOut The buffer to hold the encoded value. MUST be large enough to hold the encoding
65    @return The size of the encoding in bytes
66    */
67    static size_t encodeLiteUInt32(const uint32_t* in, size_t num, uint8_t* encodeOut);
68
69    /** Encode an array of uint32_t
70    @param in The values to encode
71    @param num The amount of values to encode
72    @param encodeOut The buffer to hold the encoded value.
73    */
74    static void encodeLiteUInt32(const uint32_t* in, size_t num, List<uint8_t>& encodeOut);
75
76    /** Encode an array of uint32_t
77    @param encodeIn The encoded values
78    @param numValues The amount of values to be decoded (NOTE! This is the number of valuesOut, not
79    encodeIn)
80    @param valuesOut The buffer to hold the encoded value. MUST be large enough to hold the encoding
81    @return The amount of bytes decoded
82    */
83    static size_t decodeLiteUInt32(const uint8_t* encodeIn, size_t numValues, uint32_t* valuesOut);
84
85    /// Table that maps 8 bits to it's most significant bit. If 0 returns -1.
86    static const int8_t s_msb8[256];
87};
88
89#if SLANG_VC
90// Works on ARM and x86/64 on visual studio compiler
91
92// ---------------------------------------------------------------------------
93SLANG_FORCE_INLINE int ByteEncodeUtil::calcNonZeroMsByte32(uint32_t in)
94{
95    SLANG_ASSERT(in != 0);
96    // Can use intrinsic
97    // https://msdn.microsoft.com/en-us/library/fbxyd7zd.aspx
98    unsigned long index;
99    _BitScanReverse(&index, in);
100    return index >> 3;
101}
102
103// ---------------------------------------------------------------------------
104SLANG_FORCE_INLINE int ByteEncodeUtil::calcMsByte32(uint32_t in)
105{
106    if (in == 0)
107    {
108        return -1;
109    }
110    // Can use intrinsic
111    // https://msdn.microsoft.com/en-us/library/fbxyd7zd.aspx
112    unsigned long index;
113    _BitScanReverse(&index, in);
114    return index >> 3;
115}
116
117// ---------------------------------------------------------------------------
118SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsb8(uint32_t v)
119{
120    SLANG_ASSERT((v & 0xffffff00) == 0);
121    if (v == 0)
122    {
123        return -1;
124    }
125    unsigned long index;
126    _BitScanReverse(&index, v);
127    return index;
128}
129
130// ---------------------------------------------------------------------------
131SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsb32(uint32_t v)
132{
133    if (v == 0)
134    {
135        return -1;
136    }
137    unsigned long index;
138    _BitScanReverse(&index, v);
139    return index;
140}
141
142#else
143
144// ---------------------------------------------------------------------------
145SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcNonZeroMsByte32(uint32_t in)
146{
147    return (in & 0xffff0000) ? ((in & 0xff000000) ? 3 : 2) : ((in & 0x0000ff00) ? 1 : 0);
148}
149
150// ---------------------------------------------------------------------------
151SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsByte32(uint32_t in)
152{
153    return (in & 0xffff0000) ? ((in & 0xff000000) ? 3 : 2)
154                             : ((in & 0x0000ff00) ? 1 : ((in == 0) ? -1 : 0));
155}
156
157// ---------------------------------------------------------------------------
158SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsb8(uint32_t v)
159{
160    SLANG_ASSERT((v & 0xffffff00) == 0);
161    return s_msb8[v];
162}
163
164// ---------------------------------------------------------------------------
165SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsb32(uint32_t v)
166{
167    return (v & 0xffff0000) ? ((v & 0xff000000) ? s_msb8[v >> 24] + 24 : s_msb8[v >> 16] + 16)
168                            : ((v & 0x0000ff00) ? s_msb8[v >> 8] + 8 : s_msb8[v]);
169}
170
171#endif
172
173// ---------------------------------------------------------------------------
174inline /* static */ size_t ByteEncodeUtil::calcEncodeLiteSizeUInt32(uint32_t v)
175{
176    if (v < kLiteCut1)
177    {
178        return 1;
179    }
180    else if (v <= kLiteCut1 + 255 * (kLiteCut2 - 1 - kLiteCut1))
181    {
182        return 2;
183    }
184    else
185    {
186        return calcNonZeroMsByte32(v) + 2;
187    }
188}
189
190} // namespace Slang
191
192#endif // SLANG_BYTE_ENCODE_UTIL_H