2
2
#define SLANG_PRELUDE_CPP_TYPES_H
3
3
4
4
#ifndef SLANG_PRELUDE_ASSERT
5
- # ifdef _DEBUG
5
+ # ifdef SLANG_PRELUDE_ENABLE_ASSERT
6
6
# define SLANG_PRELUDE_ASSERT (VALUE ) assert(VALUE)
7
7
# else
8
8
# define SLANG_PRELUDE_ASSERT (VALUE )
9
9
# endif
10
10
#endif
11
11
12
- #ifndef SLANG_FORCE_INLINE
13
- # define SLANG_FORCE_INLINE inline
12
+ // Since we are using unsigned arithmatic care is need in this comparison.
13
+ // It is *assumed* that sizeInBytes >= elemSize. Which means (sizeInBytes >= elemSize) >= 0
14
+ // Which means only a single test is needed
15
+
16
+ // Asserts for bounds checking.
17
+ // It is assumed index/count are unsigned types.
18
+ #define SLANG_BOUND_ASSERT (index, count ) SLANG_PRELUDE_ASSERT(index < count);
19
+ #define SLANG_BOUND_ASSERT_BYTE_ADDRESS (index, elemSize, sizeInBytes ) SLANG_PRELUDE_ASSERT(index <= (sizeInBytes - elemSize) && (index & 3 ) == 0 );
20
+
21
+ // Macros to zero index if an access is out of range
22
+ #define SLANG_BOUND_ZERO_INDEX (index, count ) index = (index < count) ? index : 0 ;
23
+ #define SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS (index, elemSize, sizeInBytes ) index = (index <= (sizeInBytes - elemSize)) ? index : 0 ;
24
+
25
+ // The 'FIX' macro define how the index is fixed. The default is to do nothing. If SLANG_ENABLE_BOUND_ZERO_INDEX
26
+ // the fix macro will zero the index, if out of range
27
+ #ifdef SLANG_ENABLE_BOUND_ZERO_INDEX
28
+ # define SLANG_BOUND_FIX (index, count ) SLANG_BOUND_ZERO_INDEX(index, count)
29
+ # define SLANG_BOUND_FIX_BYTE_ADDRESS (index, elemSize, sizeInBytes ) SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes)
30
+ # define SLANG_BOUND_FIX_FIXED_ARRAY (index, count ) SLANG_BOUND_ZERO_INDEX(index, count)
31
+ #else
32
+ # define SLANG_BOUND_FIX (index, count )
33
+ # define SLANG_BOUND_FIX_BYTE_ADDRESS (index, elemSize, sizeInBytes )
34
+ # define SLANG_BOUND_FIX_FIXED_ARRAY (index, count )
35
+ #endif
36
+
37
+ #ifndef SLANG_BOUND_CHECK
38
+ # define SLANG_BOUND_CHECK (index, count ) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX(index, count)
39
+ #endif
40
+
41
+ #ifndef SLANG_BOUND_CHECK_BYTE_ADDRESS
42
+ # define SLANG_BOUND_CHECK_BYTE_ADDRESS (index, elemSize, sizeInBytes ) SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes)
43
+ #endif
44
+
45
+ #ifndef SLANG_BOUND_CHECK_FIXED_ARRAY
46
+ # define SLANG_BOUND_CHECK_FIXED_ARRAY (index, count ) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX_FIXED_ARRAY(index, count)
14
47
#endif
15
48
16
49
#ifdef SLANG_PRELUDE_NAMESPACE
@@ -25,8 +58,8 @@ struct TypeInfo
25
58
template <typename T, size_t SIZE>
26
59
struct FixedArray
27
60
{
28
- const T& operator [](size_t index) const { SLANG_PRELUDE_ASSERT (index < SIZE); return m_data[index ]; }
29
- T& operator [](size_t index) { SLANG_PRELUDE_ASSERT (index < SIZE); return m_data[index ]; }
61
+ const T& operator [](size_t index) const { SLANG_BOUND_CHECK_FIXED_ARRAY (index , SIZE); return m_data[index ]; }
62
+ T& operator [](size_t index) { SLANG_BOUND_CHECK_FIXED_ARRAY (index , SIZE); return m_data[index ]; }
30
63
31
64
T m_data[SIZE];
32
65
};
@@ -36,8 +69,8 @@ struct FixedArray
36
69
template <typename T>
37
70
struct Array
38
71
{
39
- const T& operator [](size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
40
- T& operator [](size_t index) { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
72
+ const T& operator [](size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
73
+ T& operator [](size_t index) { SLANG_BOUND_CHECK (index , count); return data[index ]; }
41
74
42
75
T* data;
43
76
size_t count;
@@ -126,8 +159,8 @@ typedef size_t NonUniformResourceIndex;
126
159
template <typename T>
127
160
struct RWStructuredBuffer
128
161
{
129
- SLANG_FORCE_INLINE T& operator [](size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
130
- const T& Load (size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
162
+ SLANG_FORCE_INLINE T& operator [](size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
163
+ const T& Load (size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
131
164
void GetDimensions (uint32_t * outNumStructs, uint32_t * outStride) { *outNumStructs = uint32_t (count); *outStride = uint32_t (sizeof (T)); }
132
165
133
166
T* data;
@@ -137,8 +170,8 @@ struct RWStructuredBuffer
137
170
template <typename T>
138
171
struct StructuredBuffer
139
172
{
140
- SLANG_FORCE_INLINE const T& operator [](size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
141
- const T& Load (size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
173
+ SLANG_FORCE_INLINE const T& operator [](size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
174
+ const T& Load (size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
142
175
void GetDimensions (uint32_t * outNumStructs, uint32_t * outStride) { *outNumStructs = uint32_t (count); *outStride = uint32_t (sizeof (T)); }
143
176
144
177
T* data;
@@ -149,8 +182,8 @@ struct StructuredBuffer
149
182
template <typename T>
150
183
struct RWBuffer
151
184
{
152
- SLANG_FORCE_INLINE T& operator [](size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
153
- const T& Load (size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
185
+ SLANG_FORCE_INLINE T& operator [](size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
186
+ const T& Load (size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
154
187
void GetDimensions (uint32_t * outCount) { *outCount = uint32_t (count); }
155
188
156
189
T* data;
@@ -160,8 +193,8 @@ struct RWBuffer
160
193
template <typename T>
161
194
struct Buffer
162
195
{
163
- SLANG_FORCE_INLINE const T& operator [](size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
164
- const T& Load (size_t index) const { SLANG_PRELUDE_ASSERT (index < count); return data[index ]; }
196
+ SLANG_FORCE_INLINE const T& operator [](size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
197
+ const T& Load (size_t index) const { SLANG_BOUND_CHECK (index , count); return data[index ]; }
165
198
void GetDimensions (uint32_t * outCount) { *outCount = uint32_t (count); }
166
199
167
200
T* data;
@@ -174,32 +207,32 @@ struct ByteAddressBuffer
174
207
void GetDimensions (uint32_t * outDim) const { *outDim = uint32_t (sizeInBytes); }
175
208
uint32_t Load (size_t index) const
176
209
{
177
- SLANG_PRELUDE_ASSERT (index + 4 <= sizeInBytes && ( index & 3 ) == 0 );
210
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 4 , sizeInBytes);
178
211
return data[index >> 2 ];
179
212
}
180
213
uint2 Load2 (size_t index) const
181
214
{
182
- SLANG_PRELUDE_ASSERT (index + 8 <= sizeInBytes && ( index & 3 ) == 0 );
215
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 8 , sizeInBytes);
183
216
const size_t dataIdx = index >> 2 ;
184
217
return uint2{data[dataIdx], data[dataIdx + 1 ]};
185
218
}
186
219
uint3 Load3 (size_t index) const
187
220
{
188
- SLANG_PRELUDE_ASSERT (index + 12 <= sizeInBytes && ( index & 3 ) == 0 );
221
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 12 , sizeInBytes);
189
222
const size_t dataIdx = index >> 2 ;
190
223
return uint3{data[dataIdx], data[dataIdx + 1 ], data[dataIdx + 2 ]};
191
224
}
192
225
uint4 Load4 (size_t index) const
193
226
{
194
- SLANG_PRELUDE_ASSERT (index + 16 <= sizeInBytes && ( index & 3 ) == 0 );
227
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 16 , sizeInBytes);
195
228
const size_t dataIdx = index >> 2 ;
196
229
return uint4{data[dataIdx], data[dataIdx + 1 ], data[dataIdx + 2 ], data[dataIdx + 3 ]};
197
230
}
198
231
template <typename T>
199
- T Load (size_t offset ) const
232
+ T Load (size_t index ) const
200
233
{
201
- SLANG_PRELUDE_ASSERT (offset + sizeof (T) <= sizeInBytes && (offset & ( alignof (T)- 1 )) == 0 );
202
- return *(T const *)((char *)data + offset );
234
+ SLANG_BOUND_CHECK_BYTE_ADDRESS ( index , sizeof (T), sizeInBytes);
235
+ return *(const T *)((( const char *)data) + index );
203
236
}
204
237
205
238
const uint32_t * data;
@@ -215,68 +248,68 @@ struct RWByteAddressBuffer
215
248
216
249
uint32_t Load (size_t index) const
217
250
{
218
- SLANG_PRELUDE_ASSERT (index + 4 <= sizeInBytes && ( index & 3 ) == 0 );
251
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 4 , sizeInBytes);
219
252
return data[index >> 2 ];
220
253
}
221
254
uint2 Load2 (size_t index) const
222
255
{
223
- SLANG_PRELUDE_ASSERT (index + 8 <= sizeInBytes && ( index & 3 ) == 0 );
256
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 8 , sizeInBytes);
224
257
const size_t dataIdx = index >> 2 ;
225
258
return uint2{data[dataIdx], data[dataIdx + 1 ]};
226
259
}
227
260
uint3 Load3 (size_t index) const
228
261
{
229
- SLANG_PRELUDE_ASSERT (index + 12 <= sizeInBytes && ( index & 3 ) == 0 );
262
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 12 , sizeInBytes);
230
263
const size_t dataIdx = index >> 2 ;
231
264
return uint3{data[dataIdx], data[dataIdx + 1 ], data[dataIdx + 2 ]};
232
265
}
233
266
uint4 Load4 (size_t index) const
234
267
{
235
- SLANG_PRELUDE_ASSERT (index + 16 <= sizeInBytes && ( index & 3 ) == 0 );
268
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 16 , sizeInBytes);
236
269
const size_t dataIdx = index >> 2 ;
237
270
return uint4{data[dataIdx], data[dataIdx + 1 ], data[dataIdx + 2 ], data[dataIdx + 3 ]};
238
271
}
239
272
template <typename T>
240
- T Load (size_t offset ) const
273
+ T Load (size_t index ) const
241
274
{
242
- SLANG_PRELUDE_ASSERT (offset + sizeof (T) <= sizeInBytes && (offset & ( alignof (T)- 1 )) == 0 );
243
- return *(T const *)((char *)data + offset );
275
+ SLANG_BOUND_CHECK_BYTE_ADDRESS ( index , sizeof (T), sizeInBytes);
276
+ return *(const T *)((( const char *)data) + index );
244
277
}
245
278
246
279
void Store (size_t index, uint32_t v) const
247
280
{
248
- SLANG_PRELUDE_ASSERT (index + 4 <= sizeInBytes && ( index & 3 ) == 0 );
281
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 4 , sizeInBytes);
249
282
data[index >> 2 ] = v;
250
283
}
251
284
void Store2 (size_t index, uint2 v) const
252
285
{
253
- SLANG_PRELUDE_ASSERT (index + 8 <= sizeInBytes && ( index & 3 ) == 0 );
286
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 8 , sizeInBytes);
254
287
const size_t dataIdx = index >> 2 ;
255
288
data[dataIdx + 0 ] = v.x ;
256
289
data[dataIdx + 1 ] = v.y ;
257
290
}
258
291
void Store3 (size_t index, uint3 v) const
259
- {
260
- SLANG_PRELUDE_ASSERT (index + 12 <= sizeInBytes && ( index & 3 ) == 0 );
292
+ {
293
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 12 , sizeInBytes);
261
294
const size_t dataIdx = index >> 2 ;
262
295
data[dataIdx + 0 ] = v.x ;
263
296
data[dataIdx + 1 ] = v.y ;
264
297
data[dataIdx + 2 ] = v.z ;
265
298
}
266
299
void Store4 (size_t index, uint4 v) const
267
300
{
268
- SLANG_PRELUDE_ASSERT (index + 16 <= sizeInBytes && ( index & 3 ) == 0 );
301
+ SLANG_BOUND_CHECK_BYTE_ADDRESS (index , 16 , sizeInBytes);
269
302
const size_t dataIdx = index >> 2 ;
270
303
data[dataIdx + 0 ] = v.x ;
271
304
data[dataIdx + 1 ] = v.y ;
272
305
data[dataIdx + 2 ] = v.z ;
273
306
data[dataIdx + 3 ] = v.w ;
274
307
}
275
308
template <typename T>
276
- void Store (size_t offset , T const & value) const
309
+ void Store (size_t index , T const & value) const
277
310
{
278
- SLANG_PRELUDE_ASSERT (offset + sizeof (T) <= sizeInBytes && (offset & ( alignof (T)- 1 )) == 0 );
279
- *(T*)((char *)data + offset ) = value;
311
+ SLANG_BOUND_CHECK_BYTE_ADDRESS ( index , sizeof (T), sizeInBytes);
312
+ *(T*)((( char *)data) + index ) = value;
280
313
}
281
314
282
315
uint32_t * data;
0 commit comments