1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Reference Renderer
3 * -----------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Vertex attribute fetch.
22 *//*--------------------------------------------------------------------*/
23
24 #include "rrVertexAttrib.hpp"
25 #include "tcuFloat.hpp"
26 #include "deInt32.h"
27 #include "deMemory.h"
28
29 namespace rr
30 {
31
32 namespace
33 {
34
35 struct NormalOrder
36 {
37 enum
38 {
39 T0 = 0,
40 T1 = 1,
41 T2 = 2,
42 T3 = 3,
43 };
44 };
45
46 struct BGRAOrder
47 {
48 enum
49 {
50 T0 = 2,
51 T1 = 1,
52 T2 = 0,
53 T3 = 3,
54 };
55 };
56
57 // readers
58
59 template <typename SrcScalarType, typename DstScalarType, typename Order>
readOrder(typename tcu::Vector<DstScalarType,4> & dst,const int size,const void * ptr)60 inline void readOrder(typename tcu::Vector<DstScalarType, 4> &dst, const int size, const void *ptr)
61 {
62 SrcScalarType aligned[4];
63 deMemcpy(aligned, ptr, size * sizeof(SrcScalarType));
64
65 dst[Order::T0] = DstScalarType(aligned[0]);
66 if (size >= 2)
67 dst[Order::T1] = DstScalarType(aligned[1]);
68 if (size >= 3)
69 dst[Order::T2] = DstScalarType(aligned[2]);
70 if (size >= 4)
71 dst[Order::T3] = DstScalarType(aligned[3]);
72 }
73
74 template <typename SrcScalarType, typename Order>
readUnormOrder(tcu::Vec4 & dst,const int size,const void * ptr)75 inline void readUnormOrder(tcu::Vec4 &dst, const int size, const void *ptr)
76 {
77 const uint32_t range = (uint32_t)((1ull << (sizeof(SrcScalarType) * 8)) - 1);
78
79 SrcScalarType aligned[4];
80 deMemcpy(aligned, ptr, size * sizeof(SrcScalarType));
81
82 dst[Order::T0] = float(aligned[0]) / float(range);
83 if (size >= 2)
84 dst[Order::T1] = float(aligned[1]) / float(range);
85 if (size >= 3)
86 dst[Order::T2] = float(aligned[2]) / float(range);
87 if (size >= 4)
88 dst[Order::T3] = float(aligned[3]) / float(range);
89 }
90
91 template <typename SrcScalarType>
readSnormClamp(tcu::Vec4 & dst,const int size,const void * ptr)92 inline void readSnormClamp(tcu::Vec4 &dst, const int size, const void *ptr)
93 {
94 // Clamped formats, GLES3-style conversion: max{c / (2^(b-1) - 1), -1 }
95 const uint32_t range = (uint32_t)((1ull << (sizeof(SrcScalarType) * 8 - 1)) - 1);
96
97 SrcScalarType aligned[4];
98 deMemcpy(aligned, ptr, size * sizeof(SrcScalarType));
99
100 dst[0] = de::max(-1.0f, float(aligned[0]) / float(range));
101 if (size >= 2)
102 dst[1] = de::max(-1.0f, float(aligned[1]) / float(range));
103 if (size >= 3)
104 dst[2] = de::max(-1.0f, float(aligned[2]) / float(range));
105 if (size >= 4)
106 dst[3] = de::max(-1.0f, float(aligned[3]) / float(range));
107 }
108
109 template <typename SrcScalarType>
readSnormScale(tcu::Vec4 & dst,const int size,const void * ptr)110 inline void readSnormScale(tcu::Vec4 &dst, const int size, const void *ptr)
111 {
112 // Scaled formats, GLES2-style conversion: (2c + 1) / (2^b - 1)
113 const uint32_t range = (uint32_t)((1ull << (sizeof(SrcScalarType) * 8)) - 1);
114
115 SrcScalarType aligned[4];
116 deMemcpy(aligned, ptr, size * sizeof(SrcScalarType));
117
118 dst[0] = (float(aligned[0]) * 2.0f + 1.0f) / float(range);
119 if (size >= 2)
120 dst[1] = (float(aligned[1]) * 2.0f + 1.0f) / float(range);
121 if (size >= 3)
122 dst[2] = (float(aligned[2]) * 2.0f + 1.0f) / float(range);
123 if (size >= 4)
124 dst[3] = (float(aligned[3]) * 2.0f + 1.0f) / float(range);
125 }
126
readHalf(tcu::Vec4 & dst,const int size,const void * ptr)127 inline void readHalf(tcu::Vec4 &dst, const int size, const void *ptr)
128 {
129 uint16_t aligned[4];
130 deMemcpy(aligned, ptr, size * sizeof(uint16_t));
131
132 dst[0] = tcu::Float16(aligned[0]).asFloat();
133 if (size >= 2)
134 dst[1] = tcu::Float16(aligned[1]).asFloat();
135 if (size >= 3)
136 dst[2] = tcu::Float16(aligned[2]).asFloat();
137 if (size >= 4)
138 dst[3] = tcu::Float16(aligned[3]).asFloat();
139 }
140
readFixed(tcu::Vec4 & dst,const int size,const void * ptr)141 inline void readFixed(tcu::Vec4 &dst, const int size, const void *ptr)
142 {
143 int32_t aligned[4];
144 deMemcpy(aligned, ptr, size * sizeof(int32_t));
145
146 dst[0] = float(aligned[0]) / float(1 << 16);
147 if (size >= 2)
148 dst[1] = float(aligned[1]) / float(1 << 16);
149 if (size >= 3)
150 dst[2] = float(aligned[2]) / float(1 << 16);
151 if (size >= 4)
152 dst[3] = float(aligned[3]) / float(1 << 16);
153 }
154
readDouble(tcu::Vec4 & dst,const int size,const void * ptr)155 inline void readDouble(tcu::Vec4 &dst, const int size, const void *ptr)
156 {
157 double aligned[4];
158 deMemcpy(aligned, ptr, size * sizeof(double));
159
160 dst[0] = float(aligned[0]);
161 if (size >= 2)
162 dst[1] = float(aligned[1]);
163 if (size >= 3)
164 dst[2] = float(aligned[2]);
165 if (size >= 4)
166 dst[3] = float(aligned[3]);
167 }
168
169 template <int integerLen>
extendSign(uint32_t integer)170 inline int32_t extendSign(uint32_t integer)
171 {
172 return uint32_t(0 - int32_t((integer & (1 << (integerLen - 1))) << 1)) | integer;
173 }
174
175 template <typename DstScalarType>
readUint2101010Rev(typename tcu::Vector<DstScalarType,4> & dst,const int size,const void * ptr)176 inline void readUint2101010Rev(typename tcu::Vector<DstScalarType, 4> &dst, const int size, const void *ptr)
177 {
178 uint32_t aligned;
179 deMemcpy(&aligned, ptr, sizeof(uint32_t));
180
181 dst[0] = DstScalarType((aligned >> 0) & ((1 << 10) - 1));
182 if (size >= 2)
183 dst[1] = DstScalarType((aligned >> 10) & ((1 << 10) - 1));
184 if (size >= 3)
185 dst[2] = DstScalarType((aligned >> 20) & ((1 << 10) - 1));
186 if (size >= 4)
187 dst[3] = DstScalarType((aligned >> 30) & ((1 << 2) - 1));
188 }
189
190 template <typename DstScalarType>
readInt2101010Rev(typename tcu::Vector<DstScalarType,4> & dst,const int size,const void * ptr)191 inline void readInt2101010Rev(typename tcu::Vector<DstScalarType, 4> &dst, const int size, const void *ptr)
192 {
193 uint32_t aligned;
194 deMemcpy(&aligned, ptr, sizeof(uint32_t));
195
196 dst[0] = (DstScalarType)extendSign<10>((aligned >> 0) & ((1 << 10) - 1));
197 if (size >= 2)
198 dst[1] = (DstScalarType)extendSign<10>((aligned >> 10) & ((1 << 10) - 1));
199 if (size >= 3)
200 dst[2] = (DstScalarType)extendSign<10>((aligned >> 20) & ((1 << 10) - 1));
201 if (size >= 4)
202 dst[3] = (DstScalarType)extendSign<2>((aligned >> 30) & ((1 << 2) - 1));
203 }
204
205 template <typename Order>
readUnorm2101010RevOrder(tcu::Vec4 & dst,const int size,const void * ptr)206 inline void readUnorm2101010RevOrder(tcu::Vec4 &dst, const int size, const void *ptr)
207 {
208 const uint32_t range10 = (uint32_t)((1ull << 10) - 1);
209 const uint32_t range2 = (uint32_t)((1ull << 2) - 1);
210
211 uint32_t aligned;
212 deMemcpy(&aligned, ptr, sizeof(uint32_t));
213
214 dst[Order::T0] = float((aligned >> 0) & ((1 << 10) - 1)) / float(range10);
215 if (size >= 2)
216 dst[Order::T1] = float((aligned >> 10) & ((1 << 10) - 1)) / float(range10);
217 if (size >= 3)
218 dst[Order::T2] = float((aligned >> 20) & ((1 << 10) - 1)) / float(range10);
219 if (size >= 4)
220 dst[Order::T3] = float((aligned >> 30) & ((1 << 2) - 1)) / float(range2);
221 }
222
223 template <typename Order>
readSnorm2101010RevClampOrder(tcu::Vec4 & dst,const int size,const void * ptr)224 inline void readSnorm2101010RevClampOrder(tcu::Vec4 &dst, const int size, const void *ptr)
225 {
226 // Clamped formats, GLES3-style conversion: max{c / (2^(b-1) - 1), -1 }
227 const uint32_t range10 = (uint32_t)((1ull << (10 - 1)) - 1);
228 const uint32_t range2 = (uint32_t)((1ull << (2 - 1)) - 1);
229
230 uint32_t aligned;
231 deMemcpy(&aligned, ptr, sizeof(uint32_t));
232
233 dst[Order::T0] = de::max(-1.0f, float(extendSign<10>((aligned >> 0) & ((1 << 10) - 1))) / float(range10));
234 if (size >= 2)
235 dst[Order::T1] = de::max(-1.0f, float(extendSign<10>((aligned >> 10) & ((1 << 10) - 1))) / float(range10));
236 if (size >= 3)
237 dst[Order::T2] = de::max(-1.0f, float(extendSign<10>((aligned >> 20) & ((1 << 10) - 1))) / float(range10));
238 if (size >= 4)
239 dst[Order::T3] = de::max(-1.0f, float(extendSign<2>((aligned >> 30) & ((1 << 2) - 1))) / float(range2));
240 }
241
242 template <typename Order>
readSnorm2101010RevScaleOrder(tcu::Vec4 & dst,const int size,const void * ptr)243 inline void readSnorm2101010RevScaleOrder(tcu::Vec4 &dst, const int size, const void *ptr)
244 {
245 // Scaled formats, GLES2-style conversion: (2c + 1) / (2^b - 1)
246 const uint32_t range10 = (uint32_t)((1ull << 10) - 1);
247 const uint32_t range2 = (uint32_t)((1ull << 2) - 1);
248
249 uint32_t aligned;
250 deMemcpy(&aligned, ptr, sizeof(uint32_t));
251
252 dst[Order::T0] = (float(extendSign<10>((aligned >> 0) & ((1 << 10) - 1))) * 2.0f + 1.0f) / float(range10);
253 if (size >= 2)
254 dst[Order::T1] = (float(extendSign<10>((aligned >> 10) & ((1 << 10) - 1))) * 2.0f + 1.0f) / float(range10);
255 if (size >= 3)
256 dst[Order::T2] = (float(extendSign<10>((aligned >> 20) & ((1 << 10) - 1))) * 2.0f + 1.0f) / float(range10);
257 if (size >= 4)
258 dst[Order::T3] = (float(extendSign<2>((aligned >> 30) & ((1 << 2) - 1))) * 2.0f + 1.0f) / float(range2);
259 }
260
261 // ordered readers
262
263 template <typename SrcScalarType, typename DstScalarType>
read(typename tcu::Vector<DstScalarType,4> & dst,const int size,const void * ptr)264 inline void read(typename tcu::Vector<DstScalarType, 4> &dst, const int size, const void *ptr)
265 {
266 readOrder<SrcScalarType, DstScalarType, NormalOrder>(dst, size, ptr);
267 }
268
269 template <typename SrcScalarType>
readUnorm(tcu::Vec4 & dst,const int size,const void * ptr)270 inline void readUnorm(tcu::Vec4 &dst, const int size, const void *ptr)
271 {
272 readUnormOrder<SrcScalarType, NormalOrder>(dst, size, ptr);
273 }
274
275 template <typename SrcScalarType>
readUnormBGRA(tcu::Vec4 & dst,const int size,const void * ptr)276 inline void readUnormBGRA(tcu::Vec4 &dst, const int size, const void *ptr)
277 {
278 readUnormOrder<SrcScalarType, BGRAOrder>(dst, size, ptr);
279 }
280
readUnorm2101010Rev(tcu::Vec4 & dst,const int size,const void * ptr)281 inline void readUnorm2101010Rev(tcu::Vec4 &dst, const int size, const void *ptr)
282 {
283 readUnorm2101010RevOrder<NormalOrder>(dst, size, ptr);
284 }
285
readUnorm2101010RevBGRA(tcu::Vec4 & dst,const int size,const void * ptr)286 inline void readUnorm2101010RevBGRA(tcu::Vec4 &dst, const int size, const void *ptr)
287 {
288 readUnorm2101010RevOrder<BGRAOrder>(dst, size, ptr);
289 }
290
readSnorm2101010RevClamp(tcu::Vec4 & dst,const int size,const void * ptr)291 inline void readSnorm2101010RevClamp(tcu::Vec4 &dst, const int size, const void *ptr)
292 {
293 readSnorm2101010RevClampOrder<NormalOrder>(dst, size, ptr);
294 }
295
readSnorm2101010RevClampBGRA(tcu::Vec4 & dst,const int size,const void * ptr)296 inline void readSnorm2101010RevClampBGRA(tcu::Vec4 &dst, const int size, const void *ptr)
297 {
298 readSnorm2101010RevClampOrder<BGRAOrder>(dst, size, ptr);
299 }
300
readSnorm2101010RevScale(tcu::Vec4 & dst,const int size,const void * ptr)301 inline void readSnorm2101010RevScale(tcu::Vec4 &dst, const int size, const void *ptr)
302 {
303 readSnorm2101010RevScaleOrder<NormalOrder>(dst, size, ptr);
304 }
305
readSnorm2101010RevScaleBGRA(tcu::Vec4 & dst,const int size,const void * ptr)306 inline void readSnorm2101010RevScaleBGRA(tcu::Vec4 &dst, const int size, const void *ptr)
307 {
308 readSnorm2101010RevScaleOrder<BGRAOrder>(dst, size, ptr);
309 }
310
311 // utils
312
readFloat(tcu::Vec4 & dst,const VertexAttribType type,const int size,const void * ptr)313 void readFloat(tcu::Vec4 &dst, const VertexAttribType type, const int size, const void *ptr)
314 {
315 switch (type)
316 {
317 case VERTEXATTRIBTYPE_FLOAT:
318 read<float>(dst, size, ptr);
319 break;
320 case VERTEXATTRIBTYPE_HALF:
321 readHalf(dst, size, ptr);
322 break;
323 case VERTEXATTRIBTYPE_FIXED:
324 readFixed(dst, size, ptr);
325 break;
326 case VERTEXATTRIBTYPE_DOUBLE:
327 readDouble(dst, size, ptr);
328 break;
329 case VERTEXATTRIBTYPE_NONPURE_UNORM8:
330 readUnorm<uint8_t>(dst, size, ptr);
331 break;
332 case VERTEXATTRIBTYPE_NONPURE_UNORM16:
333 readUnorm<uint16_t>(dst, size, ptr);
334 break;
335 case VERTEXATTRIBTYPE_NONPURE_UNORM32:
336 readUnorm<uint32_t>(dst, size, ptr);
337 break;
338 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV:
339 readUnorm2101010Rev(dst, size, ptr);
340 break;
341 case VERTEXATTRIBTYPE_NONPURE_SNORM8_CLAMP:
342 readSnormClamp<int8_t>(dst, size, ptr);
343 break;
344 case VERTEXATTRIBTYPE_NONPURE_SNORM16_CLAMP:
345 readSnormClamp<int16_t>(dst, size, ptr);
346 break;
347 case VERTEXATTRIBTYPE_NONPURE_SNORM32_CLAMP:
348 readSnormClamp<int32_t>(dst, size, ptr);
349 break;
350 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP:
351 readSnorm2101010RevClamp(dst, size, ptr);
352 break;
353 case VERTEXATTRIBTYPE_NONPURE_SNORM8_SCALE:
354 readSnormScale<int8_t>(dst, size, ptr);
355 break;
356 case VERTEXATTRIBTYPE_NONPURE_SNORM16_SCALE:
357 readSnormScale<int16_t>(dst, size, ptr);
358 break;
359 case VERTEXATTRIBTYPE_NONPURE_SNORM32_SCALE:
360 readSnormScale<int32_t>(dst, size, ptr);
361 break;
362 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE:
363 readSnorm2101010RevScale(dst, size, ptr);
364 break;
365 case VERTEXATTRIBTYPE_NONPURE_UINT8:
366 read<uint8_t>(dst, size, ptr);
367 break;
368 case VERTEXATTRIBTYPE_NONPURE_UINT16:
369 read<uint16_t>(dst, size, ptr);
370 break;
371 case VERTEXATTRIBTYPE_NONPURE_UINT32:
372 read<uint32_t>(dst, size, ptr);
373 break;
374 case VERTEXATTRIBTYPE_NONPURE_INT8:
375 read<int8_t>(dst, size, ptr);
376 break;
377 case VERTEXATTRIBTYPE_NONPURE_INT16:
378 read<int16_t>(dst, size, ptr);
379 break;
380 case VERTEXATTRIBTYPE_NONPURE_INT32:
381 read<int32_t>(dst, size, ptr);
382 break;
383 case VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV:
384 readUint2101010Rev(dst, size, ptr);
385 break;
386 case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:
387 readInt2101010Rev(dst, size, ptr);
388 break;
389 case VERTEXATTRIBTYPE_NONPURE_UNORM8_BGRA:
390 readUnormBGRA<uint8_t>(dst, size, ptr);
391 break;
392 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA:
393 readUnorm2101010RevBGRA(dst, size, ptr);
394 break;
395 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:
396 readSnorm2101010RevClampBGRA(dst, size, ptr);
397 break;
398 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:
399 readSnorm2101010RevScaleBGRA(dst, size, ptr);
400 break;
401
402 case VERTEXATTRIBTYPE_PURE_UINT8:
403 case VERTEXATTRIBTYPE_PURE_UINT16:
404 case VERTEXATTRIBTYPE_PURE_UINT32:
405 case VERTEXATTRIBTYPE_PURE_INT8:
406 case VERTEXATTRIBTYPE_PURE_INT16:
407 case VERTEXATTRIBTYPE_PURE_INT32:
408 DE_FATAL("Invalid read");
409 break;
410
411 default:
412 DE_ASSERT(false);
413 }
414 }
415
readInt(tcu::IVec4 & dst,const VertexAttribType type,const int size,const void * ptr)416 void readInt(tcu::IVec4 &dst, const VertexAttribType type, const int size, const void *ptr)
417 {
418 switch (type)
419 {
420 case VERTEXATTRIBTYPE_PURE_INT8:
421 read<int8_t>(dst, size, ptr);
422 break;
423 case VERTEXATTRIBTYPE_PURE_INT16:
424 read<int16_t>(dst, size, ptr);
425 break;
426 case VERTEXATTRIBTYPE_PURE_INT32:
427 read<int32_t>(dst, size, ptr);
428 break;
429
430 case VERTEXATTRIBTYPE_FLOAT:
431 case VERTEXATTRIBTYPE_HALF:
432 case VERTEXATTRIBTYPE_FIXED:
433 case VERTEXATTRIBTYPE_DOUBLE:
434 case VERTEXATTRIBTYPE_NONPURE_UNORM8:
435 case VERTEXATTRIBTYPE_NONPURE_UNORM16:
436 case VERTEXATTRIBTYPE_NONPURE_UNORM32:
437 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV:
438 case VERTEXATTRIBTYPE_NONPURE_SNORM8_CLAMP:
439 case VERTEXATTRIBTYPE_NONPURE_SNORM16_CLAMP:
440 case VERTEXATTRIBTYPE_NONPURE_SNORM32_CLAMP:
441 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP:
442 case VERTEXATTRIBTYPE_NONPURE_SNORM8_SCALE:
443 case VERTEXATTRIBTYPE_NONPURE_SNORM16_SCALE:
444 case VERTEXATTRIBTYPE_NONPURE_SNORM32_SCALE:
445 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE:
446 case VERTEXATTRIBTYPE_NONPURE_UINT8:
447 case VERTEXATTRIBTYPE_NONPURE_UINT16:
448 case VERTEXATTRIBTYPE_NONPURE_UINT32:
449 case VERTEXATTRIBTYPE_NONPURE_INT8:
450 case VERTEXATTRIBTYPE_NONPURE_INT16:
451 case VERTEXATTRIBTYPE_NONPURE_INT32:
452 case VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV:
453 case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:
454 case VERTEXATTRIBTYPE_PURE_UINT8:
455 case VERTEXATTRIBTYPE_PURE_UINT16:
456 case VERTEXATTRIBTYPE_PURE_UINT32:
457 case VERTEXATTRIBTYPE_NONPURE_UNORM8_BGRA:
458 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA:
459 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:
460 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:
461 DE_FATAL("Invalid read");
462 break;
463
464 default:
465 DE_ASSERT(false);
466 }
467 }
468
readUint(tcu::UVec4 & dst,const VertexAttribType type,const int size,const void * ptr)469 void readUint(tcu::UVec4 &dst, const VertexAttribType type, const int size, const void *ptr)
470 {
471 switch (type)
472 {
473 case VERTEXATTRIBTYPE_PURE_UINT8:
474 read<uint8_t>(dst, size, ptr);
475 break;
476 case VERTEXATTRIBTYPE_PURE_UINT16:
477 read<uint16_t>(dst, size, ptr);
478 break;
479 case VERTEXATTRIBTYPE_PURE_UINT32:
480 read<uint32_t>(dst, size, ptr);
481 break;
482
483 case VERTEXATTRIBTYPE_FLOAT:
484 case VERTEXATTRIBTYPE_HALF:
485 case VERTEXATTRIBTYPE_FIXED:
486 case VERTEXATTRIBTYPE_DOUBLE:
487 case VERTEXATTRIBTYPE_NONPURE_UNORM8:
488 case VERTEXATTRIBTYPE_NONPURE_UNORM16:
489 case VERTEXATTRIBTYPE_NONPURE_UNORM32:
490 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV:
491 case VERTEXATTRIBTYPE_NONPURE_SNORM8_CLAMP:
492 case VERTEXATTRIBTYPE_NONPURE_SNORM16_CLAMP:
493 case VERTEXATTRIBTYPE_NONPURE_SNORM32_CLAMP:
494 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP:
495 case VERTEXATTRIBTYPE_NONPURE_SNORM8_SCALE:
496 case VERTEXATTRIBTYPE_NONPURE_SNORM16_SCALE:
497 case VERTEXATTRIBTYPE_NONPURE_SNORM32_SCALE:
498 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE:
499 case VERTEXATTRIBTYPE_NONPURE_UINT8:
500 case VERTEXATTRIBTYPE_NONPURE_UINT16:
501 case VERTEXATTRIBTYPE_NONPURE_UINT32:
502 case VERTEXATTRIBTYPE_NONPURE_INT8:
503 case VERTEXATTRIBTYPE_NONPURE_INT16:
504 case VERTEXATTRIBTYPE_NONPURE_INT32:
505 case VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV:
506 case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:
507 case VERTEXATTRIBTYPE_PURE_INT8:
508 case VERTEXATTRIBTYPE_PURE_INT16:
509 case VERTEXATTRIBTYPE_PURE_INT32:
510 case VERTEXATTRIBTYPE_NONPURE_UNORM8_BGRA:
511 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA:
512 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:
513 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:
514 DE_FATAL("Invalid read");
515 break;
516
517 default:
518 DE_ASSERT(false);
519 }
520 }
521
getComponentSize(const VertexAttribType type)522 int getComponentSize(const VertexAttribType type)
523 {
524 switch (type)
525 {
526 case VERTEXATTRIBTYPE_FLOAT:
527 return 4;
528 case VERTEXATTRIBTYPE_HALF:
529 return 2;
530 case VERTEXATTRIBTYPE_FIXED:
531 return 4;
532 case VERTEXATTRIBTYPE_DOUBLE:
533 return (int)sizeof(double);
534 case VERTEXATTRIBTYPE_NONPURE_UNORM8:
535 return 1;
536 case VERTEXATTRIBTYPE_NONPURE_UNORM16:
537 return 2;
538 case VERTEXATTRIBTYPE_NONPURE_UNORM32:
539 return 4;
540 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV:
541 return (int)sizeof(uint32_t) / 4;
542 case VERTEXATTRIBTYPE_NONPURE_SNORM8_CLAMP:
543 return 1;
544 case VERTEXATTRIBTYPE_NONPURE_SNORM16_CLAMP:
545 return 2;
546 case VERTEXATTRIBTYPE_NONPURE_SNORM32_CLAMP:
547 return 4;
548 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP:
549 return (int)sizeof(uint32_t) / 4;
550 case VERTEXATTRIBTYPE_NONPURE_SNORM8_SCALE:
551 return 1;
552 case VERTEXATTRIBTYPE_NONPURE_SNORM16_SCALE:
553 return 2;
554 case VERTEXATTRIBTYPE_NONPURE_SNORM32_SCALE:
555 return 4;
556 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE:
557 return (int)sizeof(uint32_t) / 4;
558 case VERTEXATTRIBTYPE_NONPURE_UINT8:
559 return 1;
560 case VERTEXATTRIBTYPE_NONPURE_UINT16:
561 return 2;
562 case VERTEXATTRIBTYPE_NONPURE_UINT32:
563 return 4;
564 case VERTEXATTRIBTYPE_NONPURE_INT8:
565 return 1;
566 case VERTEXATTRIBTYPE_NONPURE_INT16:
567 return 2;
568 case VERTEXATTRIBTYPE_NONPURE_INT32:
569 return 4;
570 case VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV:
571 return (int)sizeof(uint32_t) / 4;
572 case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:
573 return (int)sizeof(uint32_t) / 4;
574 case VERTEXATTRIBTYPE_PURE_UINT8:
575 return 1;
576 case VERTEXATTRIBTYPE_PURE_UINT16:
577 return 2;
578 case VERTEXATTRIBTYPE_PURE_UINT32:
579 return 4;
580 case VERTEXATTRIBTYPE_PURE_INT8:
581 return 1;
582 case VERTEXATTRIBTYPE_PURE_INT16:
583 return 2;
584 case VERTEXATTRIBTYPE_PURE_INT32:
585 return 4;
586 case VERTEXATTRIBTYPE_NONPURE_UNORM8_BGRA:
587 return 1;
588 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA:
589 return (int)sizeof(uint32_t) / 4;
590 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:
591 return (int)sizeof(uint32_t) / 4;
592 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:
593 return (int)sizeof(uint32_t) / 4;
594 default:
595 DE_ASSERT(false);
596 return 0;
597 }
598 }
599
600 } // namespace
601
isValidVertexAttrib(const VertexAttrib & vertexAttrib)602 bool isValidVertexAttrib(const VertexAttrib &vertexAttrib)
603 {
604 // Trivial range checks.
605 if (!de::inBounds<int>(vertexAttrib.type, 0, VERTEXATTRIBTYPE_LAST) || !de::inRange(vertexAttrib.size, 0, 4) ||
606 vertexAttrib.instanceDivisor < 0)
607 return false;
608
609 // Generic attributes
610 if (!vertexAttrib.pointer && vertexAttrib.type != VERTEXATTRIBTYPE_DONT_CARE)
611 return false;
612
613 // Packed formats
614 if ((vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV ||
615 vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV ||
616 vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV ||
617 vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP ||
618 vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE ||
619 vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA ||
620 vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA ||
621 vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA) &&
622 vertexAttrib.size != 4)
623 return false;
624
625 return true;
626 }
627
readVertexAttrib(tcu::Vec4 & dst,const VertexAttrib & vertexAttrib,const int instanceNdx,const int vertexNdx,const int baseInstanceNdx)628 void readVertexAttrib(tcu::Vec4 &dst, const VertexAttrib &vertexAttrib, const int instanceNdx, const int vertexNdx,
629 const int baseInstanceNdx)
630 {
631 DE_ASSERT(isValidVertexAttrib(vertexAttrib));
632
633 if (vertexAttrib.pointer)
634 {
635 const int elementNdx = (vertexAttrib.instanceDivisor != 0) ?
636 baseInstanceNdx + (instanceNdx / vertexAttrib.instanceDivisor) :
637 vertexNdx;
638 const int compSize = getComponentSize(vertexAttrib.type);
639 const int stride = (vertexAttrib.stride != 0) ? (vertexAttrib.stride) : (vertexAttrib.size * compSize);
640 const int byteOffset = elementNdx * stride;
641
642 dst = tcu::Vec4(0, 0, 0, 1); // defaults
643 readFloat(dst, vertexAttrib.type, vertexAttrib.size, (const uint8_t *)vertexAttrib.pointer + byteOffset);
644 }
645 else
646 {
647 dst = vertexAttrib.generic.get<float>();
648 }
649 }
650
readVertexAttrib(tcu::IVec4 & dst,const VertexAttrib & vertexAttrib,const int instanceNdx,const int vertexNdx,const int baseInstanceNdx)651 void readVertexAttrib(tcu::IVec4 &dst, const VertexAttrib &vertexAttrib, const int instanceNdx, const int vertexNdx,
652 const int baseInstanceNdx)
653 {
654 DE_ASSERT(isValidVertexAttrib(vertexAttrib));
655
656 if (vertexAttrib.pointer)
657 {
658 const int elementNdx = (vertexAttrib.instanceDivisor != 0) ?
659 baseInstanceNdx + (instanceNdx / vertexAttrib.instanceDivisor) :
660 vertexNdx;
661 const int compSize = getComponentSize(vertexAttrib.type);
662 const int stride = (vertexAttrib.stride != 0) ? (vertexAttrib.stride) : (vertexAttrib.size * compSize);
663 const int byteOffset = elementNdx * stride;
664
665 dst = tcu::IVec4(0, 0, 0, 1); // defaults
666 readInt(dst, vertexAttrib.type, vertexAttrib.size, (const uint8_t *)vertexAttrib.pointer + byteOffset);
667 }
668 else
669 {
670 dst = vertexAttrib.generic.get<int32_t>();
671 }
672 }
673
readVertexAttrib(tcu::UVec4 & dst,const VertexAttrib & vertexAttrib,const int instanceNdx,const int vertexNdx,const int baseInstanceNdx)674 void readVertexAttrib(tcu::UVec4 &dst, const VertexAttrib &vertexAttrib, const int instanceNdx, const int vertexNdx,
675 const int baseInstanceNdx)
676 {
677 DE_ASSERT(isValidVertexAttrib(vertexAttrib));
678
679 if (vertexAttrib.pointer)
680 {
681 const int elementNdx = (vertexAttrib.instanceDivisor != 0) ?
682 baseInstanceNdx + (instanceNdx / vertexAttrib.instanceDivisor) :
683 vertexNdx;
684 const int compSize = getComponentSize(vertexAttrib.type);
685 const int stride = (vertexAttrib.stride != 0) ? (vertexAttrib.stride) : (vertexAttrib.size * compSize);
686 const int byteOffset = elementNdx * stride;
687
688 dst = tcu::UVec4(0, 0, 0, 1); // defaults
689 readUint(dst, vertexAttrib.type, vertexAttrib.size, (const uint8_t *)vertexAttrib.pointer + byteOffset);
690 }
691 else
692 {
693 dst = vertexAttrib.generic.get<uint32_t>();
694 }
695 }
696
697 } // namespace rr
698