Add CTS_ARB_gl_spirv test implementation
[platform/upstream/VK-GL-CTS.git] / framework / referencerenderer / rrVertexAttrib.cpp
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>
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) dst[Order::T1] = DstScalarType(aligned[1]);
67         if (size >= 3) dst[Order::T2] = DstScalarType(aligned[2]);
68         if (size >= 4) dst[Order::T3] = DstScalarType(aligned[3]);
69 }
70
71 template<typename SrcScalarType, typename Order>
72 inline void readUnormOrder (tcu::Vec4& dst, const int size, const void* ptr)
73 {
74         const deUint32 range = (deUint32)((1ull << (sizeof(SrcScalarType)*8))-1);
75
76         SrcScalarType aligned[4];
77         deMemcpy(aligned, ptr, size * sizeof(SrcScalarType));
78
79                                    dst[Order::T0] = float(aligned[0]) / float(range);
80         if (size >= 2) dst[Order::T1] = float(aligned[1]) / float(range);
81         if (size >= 3) dst[Order::T2] = float(aligned[2]) / float(range);
82         if (size >= 4) dst[Order::T3] = float(aligned[3]) / float(range);
83 }
84
85 template<typename SrcScalarType>
86 inline void readSnormClamp (tcu::Vec4& dst, const int size, const void* ptr)
87 {
88         // Clamped formats, GLES3-style conversion: max{c / (2^(b-1) - 1), -1 }
89         const deUint32 range = (deUint32)((1ull << (sizeof(SrcScalarType)*8-1))-1);
90
91         SrcScalarType aligned[4];
92         deMemcpy(aligned, ptr, size * sizeof(SrcScalarType));
93
94                                    dst[0] = de::max(-1.0f, float(aligned[0]) / float(range));
95         if (size >= 2) dst[1] = de::max(-1.0f, float(aligned[1]) / float(range));
96         if (size >= 3) dst[2] = de::max(-1.0f, float(aligned[2]) / float(range));
97         if (size >= 4) dst[3] = de::max(-1.0f, float(aligned[3]) / float(range));
98 }
99
100 template<typename SrcScalarType>
101 inline void readSnormScale (tcu::Vec4& dst, const int size, const void* ptr)
102 {
103         // Scaled formats, GLES2-style conversion: (2c + 1) / (2^b - 1)
104         const deUint32 range = (deUint32)((1ull << (sizeof(SrcScalarType)*8))-1);
105
106         SrcScalarType aligned[4];
107         deMemcpy(aligned, ptr, size * sizeof(SrcScalarType));
108
109                                    dst[0] = (float(aligned[0]) * 2.0f + 1.0f) / float(range);
110         if (size >= 2) dst[1] = (float(aligned[1]) * 2.0f + 1.0f) / float(range);
111         if (size >= 3) dst[2] = (float(aligned[2]) * 2.0f + 1.0f) / float(range);
112         if (size >= 4) dst[3] = (float(aligned[3]) * 2.0f + 1.0f) / float(range);
113 }
114
115 inline void readHalf (tcu::Vec4& dst, const int size, const void* ptr)
116 {
117         deUint16 aligned[4];
118         deMemcpy(aligned, ptr, size * sizeof(deUint16));
119
120                                    dst[0] = tcu::Float16(aligned[0]).asFloat();
121         if (size >= 2) dst[1] = tcu::Float16(aligned[1]).asFloat();
122         if (size >= 3) dst[2] = tcu::Float16(aligned[2]).asFloat();
123         if (size >= 4) dst[3] = tcu::Float16(aligned[3]).asFloat();
124 }
125
126 inline void readFixed (tcu::Vec4& dst, const int size, const void* ptr)
127 {
128         deInt32 aligned[4];
129         deMemcpy(aligned, ptr, size * sizeof(deInt32));
130
131                                    dst[0] = float(aligned[0]) / float(1 << 16);
132         if (size >= 2) dst[1] = float(aligned[1]) / float(1 << 16);
133         if (size >= 3) dst[2] = float(aligned[2]) / float(1 << 16);
134         if (size >= 4) dst[3] = float(aligned[3]) / float(1 << 16);
135 }
136
137 inline void readDouble (tcu::Vec4& dst, const int size, const void* ptr)
138 {
139         double aligned[4];
140         deMemcpy(aligned, ptr, size * sizeof(double));
141
142                                    dst[0] = float(aligned[0]);
143         if (size >= 2) dst[1] = float(aligned[1]);
144         if (size >= 3) dst[2] = float(aligned[2]);
145         if (size >= 4) dst[3] = float(aligned[3]);
146 }
147
148 template <int integerLen>
149 inline deInt32 extendSign (deUint32 integer)
150 {
151         return deUint32(0 - deInt32((integer & (1 << (integerLen - 1))) << 1)) | integer;
152 }
153
154 template<typename DstScalarType>
155 inline void readUint2101010Rev (typename tcu::Vector<DstScalarType, 4>& dst, const int size, const void* ptr)
156 {
157         deUint32 aligned;
158         deMemcpy(&aligned, ptr, sizeof(deUint32));
159
160                                    dst[0] = DstScalarType((aligned >>  0) & ((1 << 10) - 1));
161         if (size >= 2) dst[1] = DstScalarType((aligned >> 10) & ((1 << 10) - 1));
162         if (size >= 3) dst[2] = DstScalarType((aligned >> 20) & ((1 << 10) - 1));
163         if (size >= 4) dst[3] = DstScalarType((aligned >> 30) & ((1 <<  2) - 1));
164 }
165
166 template<typename DstScalarType>
167 inline void readInt2101010Rev (typename tcu::Vector<DstScalarType, 4>& dst, const int size, const void* ptr)
168 {
169         deUint32 aligned;
170         deMemcpy(&aligned, ptr, sizeof(deUint32));
171
172                                    dst[0] = (DstScalarType)extendSign<10>((aligned >>  0) & ((1 << 10) - 1));
173         if (size >= 2) dst[1] = (DstScalarType)extendSign<10>((aligned >> 10) & ((1 << 10) - 1));
174         if (size >= 3) dst[2] = (DstScalarType)extendSign<10>((aligned >> 20) & ((1 << 10) - 1));
175         if (size >= 4) dst[3] = (DstScalarType)extendSign< 2>((aligned >> 30) & ((1 <<  2) - 1));
176 }
177
178 template<typename Order>
179 inline void readUnorm2101010RevOrder (tcu::Vec4& dst, const int size, const void* ptr)
180 {
181         const deUint32 range10 = (deUint32)((1ull << 10)-1);
182         const deUint32 range2 = (deUint32)((1ull <<  2)-1);
183
184         deUint32 aligned;
185         deMemcpy(&aligned, ptr, sizeof(deUint32));
186
187                                    dst[Order::T0] = float((aligned >>  0) & ((1 << 10) - 1)) / float(range10);
188         if (size >= 2) dst[Order::T1] = float((aligned >> 10) & ((1 << 10) - 1)) / float(range10);
189         if (size >= 3) dst[Order::T2] = float((aligned >> 20) & ((1 << 10) - 1)) / float(range10);
190         if (size >= 4) dst[Order::T3] = float((aligned >> 30) & ((1 <<  2) - 1)) / float(range2);
191 }
192
193 template<typename Order>
194 inline void readSnorm2101010RevClampOrder (tcu::Vec4& dst, const int size, const void* ptr)
195 {
196         // Clamped formats, GLES3-style conversion: max{c / (2^(b-1) - 1), -1 }
197         const deUint32 range10 = (deUint32)((1ull << (10-1))-1);
198         const deUint32 range2  = (deUint32)((1ull << ( 2-1))-1);
199
200         deUint32 aligned;
201         deMemcpy(&aligned, ptr, sizeof(deUint32));
202
203                                    dst[Order::T0] = de::max(-1.0f, float(extendSign<10>((aligned >>  0) & ((1 << 10) - 1))) / float(range10));
204         if (size >= 2) dst[Order::T1] = de::max(-1.0f, float(extendSign<10>((aligned >> 10) & ((1 << 10) - 1))) / float(range10));
205         if (size >= 3) dst[Order::T2] = de::max(-1.0f, float(extendSign<10>((aligned >> 20) & ((1 << 10) - 1))) / float(range10));
206         if (size >= 4) dst[Order::T3] = de::max(-1.0f, float(extendSign< 2>((aligned >> 30) & ((1 <<  2) - 1))) / float(range2));
207 }
208
209 template<typename Order>
210 inline void readSnorm2101010RevScaleOrder (tcu::Vec4& dst, const int size, const void* ptr)
211 {
212         // Scaled formats, GLES2-style conversion: (2c + 1) / (2^b - 1)
213         const deUint32 range10 = (deUint32)((1ull << 10)-1);
214         const deUint32 range2  = (deUint32)((1ull <<  2)-1);
215
216         deUint32 aligned;
217         deMemcpy(&aligned, ptr, sizeof(deUint32));
218
219                                    dst[Order::T0] = (float(extendSign<10>((aligned >>  0) & ((1 << 10) - 1))) * 2.0f + 1.0f) / float(range10);
220         if (size >= 2) dst[Order::T1] = (float(extendSign<10>((aligned >> 10) & ((1 << 10) - 1))) * 2.0f + 1.0f) / float(range10);
221         if (size >= 3) dst[Order::T2] = (float(extendSign<10>((aligned >> 20) & ((1 << 10) - 1))) * 2.0f + 1.0f) / float(range10);
222         if (size >= 4) dst[Order::T3] = (float(extendSign< 2>((aligned >> 30) & ((1 <<  2) - 1))) * 2.0f + 1.0f) / float(range2);
223 }
224
225 // ordered readers
226
227 template<typename SrcScalarType, typename DstScalarType>
228 inline void read (typename tcu::Vector<DstScalarType, 4>& dst, const int size, const void* ptr)
229 {
230         readOrder<SrcScalarType, DstScalarType, NormalOrder>(dst, size, ptr);
231 }
232
233 template<typename SrcScalarType>
234 inline void readUnorm (tcu::Vec4& dst, const int size, const void* ptr)
235 {
236         readUnormOrder<SrcScalarType, NormalOrder>(dst, size, ptr);
237 }
238
239 template<typename SrcScalarType>
240 inline void readUnormBGRA (tcu::Vec4& dst, const int size, const void* ptr)
241 {
242         readUnormOrder<SrcScalarType, BGRAOrder>(dst, size, ptr);
243 }
244
245 inline void readUnorm2101010Rev (tcu::Vec4& dst, const int size, const void* ptr)
246 {
247         readUnorm2101010RevOrder<NormalOrder>(dst, size, ptr);
248 }
249
250 inline void readUnorm2101010RevBGRA (tcu::Vec4& dst, const int size, const void* ptr)
251 {
252         readUnorm2101010RevOrder<BGRAOrder>(dst, size, ptr);
253 }
254
255 inline void readSnorm2101010RevClamp (tcu::Vec4& dst, const int size, const void* ptr)
256 {
257         readSnorm2101010RevClampOrder<NormalOrder>(dst, size, ptr);
258 }
259
260 inline void readSnorm2101010RevClampBGRA (tcu::Vec4& dst, const int size, const void* ptr)
261 {
262         readSnorm2101010RevClampOrder<BGRAOrder>(dst, size, ptr);
263 }
264
265 inline void readSnorm2101010RevScale (tcu::Vec4& dst, const int size, const void* ptr)
266 {
267         readSnorm2101010RevScaleOrder<NormalOrder>(dst, size, ptr);
268 }
269
270 inline void readSnorm2101010RevScaleBGRA (tcu::Vec4& dst, const int size, const void* ptr)
271 {
272         readSnorm2101010RevScaleOrder<BGRAOrder>(dst, size, ptr);
273 }
274
275 // utils
276
277 void readFloat (tcu::Vec4& dst, const VertexAttribType type, const int size, const void* ptr)
278 {
279         switch (type)
280         {
281                 case VERTEXATTRIBTYPE_FLOAT:                                                                    read<float>                                     (dst, size, ptr);       break;
282                 case VERTEXATTRIBTYPE_HALF:                                                                             readHalf                                        (dst, size, ptr);       break;
283                 case VERTEXATTRIBTYPE_FIXED:                                                                    readFixed                                       (dst, size, ptr);       break;
284                 case VERTEXATTRIBTYPE_DOUBLE:                                                                   readDouble                                      (dst, size, ptr);       break;
285                 case VERTEXATTRIBTYPE_NONPURE_UNORM8:                                                   readUnorm<deUint8>                      (dst, size, ptr);       break;
286                 case VERTEXATTRIBTYPE_NONPURE_UNORM16:                                                  readUnorm<deUint16>                     (dst, size, ptr);       break;
287                 case VERTEXATTRIBTYPE_NONPURE_UNORM32:                                                  readUnorm<deUint32>                     (dst, size, ptr);       break;
288                 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV:                             readUnorm2101010Rev                     (dst, size, ptr);       break;
289                 case VERTEXATTRIBTYPE_NONPURE_SNORM8_CLAMP:                                             readSnormClamp<deInt8>          (dst, size, ptr);       break;
290                 case VERTEXATTRIBTYPE_NONPURE_SNORM16_CLAMP:                                    readSnormClamp<deInt16>         (dst, size, ptr);       break;
291                 case VERTEXATTRIBTYPE_NONPURE_SNORM32_CLAMP:                                    readSnormClamp<deInt32>         (dst, size, ptr);       break;
292                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP:               readSnorm2101010RevClamp        (dst, size, ptr);       break;
293                 case VERTEXATTRIBTYPE_NONPURE_SNORM8_SCALE:                                             readSnormScale<deInt8>          (dst, size, ptr);       break;
294                 case VERTEXATTRIBTYPE_NONPURE_SNORM16_SCALE:                                    readSnormScale<deInt16>         (dst, size, ptr);       break;
295                 case VERTEXATTRIBTYPE_NONPURE_SNORM32_SCALE:                                    readSnormScale<deInt32>         (dst, size, ptr);       break;
296                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE:               readSnorm2101010RevScale        (dst, size, ptr);       break;
297                 case VERTEXATTRIBTYPE_NONPURE_UINT8:                                                    read<deUint8>                           (dst, size, ptr);       break;
298                 case VERTEXATTRIBTYPE_NONPURE_UINT16:                                                   read<deUint16>                          (dst, size, ptr);       break;
299                 case VERTEXATTRIBTYPE_NONPURE_UINT32:                                                   read<deUint32>                          (dst, size, ptr);       break;
300                 case VERTEXATTRIBTYPE_NONPURE_INT8:                                                             read<deInt8>                            (dst, size, ptr);       break;
301                 case VERTEXATTRIBTYPE_NONPURE_INT16:                                                    read<deInt16>                           (dst, size, ptr);       break;
302                 case VERTEXATTRIBTYPE_NONPURE_INT32:                                                    read<deInt32>                           (dst, size, ptr);       break;
303                 case VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV:                              readUint2101010Rev                      (dst, size, ptr);       break;
304                 case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:                               readInt2101010Rev                       (dst, size, ptr);       break;
305                 case VERTEXATTRIBTYPE_NONPURE_UNORM8_BGRA:                                              readUnormBGRA<deUint8>          (dst, size, ptr);       break;
306                 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA:                readUnorm2101010RevBGRA         (dst, size, ptr);       break;
307                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:  readSnorm2101010RevClampBGRA(dst, size, ptr);   break;
308                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:  readSnorm2101010RevScaleBGRA(dst, size, ptr);   break;
309
310                 case VERTEXATTRIBTYPE_PURE_UINT8:
311                 case VERTEXATTRIBTYPE_PURE_UINT16:
312                 case VERTEXATTRIBTYPE_PURE_UINT32:
313                 case VERTEXATTRIBTYPE_PURE_INT8:
314                 case VERTEXATTRIBTYPE_PURE_INT16:
315                 case VERTEXATTRIBTYPE_PURE_INT32:
316                         DE_FATAL("Invalid read");
317
318                 default:
319                         DE_ASSERT(false);
320         }
321 }
322
323 void readInt (tcu::IVec4& dst, const VertexAttribType type, const int size, const void* ptr)
324 {
325         switch (type)
326         {
327                 case VERTEXATTRIBTYPE_PURE_INT8:                                read<deInt8>            (dst, size, ptr);       break;
328                 case VERTEXATTRIBTYPE_PURE_INT16:                               read<deInt16>           (dst, size, ptr);       break;
329                 case VERTEXATTRIBTYPE_PURE_INT32:                               read<deInt32>           (dst, size, ptr);       break;
330
331                 case VERTEXATTRIBTYPE_FLOAT:
332                 case VERTEXATTRIBTYPE_HALF:
333                 case VERTEXATTRIBTYPE_FIXED:
334                 case VERTEXATTRIBTYPE_DOUBLE:
335                 case VERTEXATTRIBTYPE_NONPURE_UNORM8:
336                 case VERTEXATTRIBTYPE_NONPURE_UNORM16:
337                 case VERTEXATTRIBTYPE_NONPURE_UNORM32:
338                 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV:
339                 case VERTEXATTRIBTYPE_NONPURE_SNORM8_CLAMP:
340                 case VERTEXATTRIBTYPE_NONPURE_SNORM16_CLAMP:
341                 case VERTEXATTRIBTYPE_NONPURE_SNORM32_CLAMP:
342                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP:
343                 case VERTEXATTRIBTYPE_NONPURE_SNORM8_SCALE:
344                 case VERTEXATTRIBTYPE_NONPURE_SNORM16_SCALE:
345                 case VERTEXATTRIBTYPE_NONPURE_SNORM32_SCALE:
346                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE:
347                 case VERTEXATTRIBTYPE_NONPURE_UINT8:
348                 case VERTEXATTRIBTYPE_NONPURE_UINT16:
349                 case VERTEXATTRIBTYPE_NONPURE_UINT32:
350                 case VERTEXATTRIBTYPE_NONPURE_INT8:
351                 case VERTEXATTRIBTYPE_NONPURE_INT16:
352                 case VERTEXATTRIBTYPE_NONPURE_INT32:
353                 case VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV:
354                 case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:
355                 case VERTEXATTRIBTYPE_PURE_UINT8:
356                 case VERTEXATTRIBTYPE_PURE_UINT16:
357                 case VERTEXATTRIBTYPE_PURE_UINT32:
358                 case VERTEXATTRIBTYPE_NONPURE_UNORM8_BGRA:
359                 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA:
360                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:
361                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:
362                         DE_FATAL("Invalid read");
363
364                 default:
365                         DE_ASSERT(false);
366         }
367 }
368
369 void readUint (tcu::UVec4& dst, const VertexAttribType type, const int size, const void* ptr)
370 {
371         switch (type)
372         {
373                 case VERTEXATTRIBTYPE_PURE_UINT8:                               read<deUint8>           (dst, size, ptr);       break;
374                 case VERTEXATTRIBTYPE_PURE_UINT16:                              read<deUint16>          (dst, size, ptr);       break;
375                 case VERTEXATTRIBTYPE_PURE_UINT32:                              read<deUint32>          (dst, size, ptr);       break;
376
377                 case VERTEXATTRIBTYPE_FLOAT:
378                 case VERTEXATTRIBTYPE_HALF:
379                 case VERTEXATTRIBTYPE_FIXED:
380                 case VERTEXATTRIBTYPE_DOUBLE:
381                 case VERTEXATTRIBTYPE_NONPURE_UNORM8:
382                 case VERTEXATTRIBTYPE_NONPURE_UNORM16:
383                 case VERTEXATTRIBTYPE_NONPURE_UNORM32:
384                 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV:
385                 case VERTEXATTRIBTYPE_NONPURE_SNORM8_CLAMP:
386                 case VERTEXATTRIBTYPE_NONPURE_SNORM16_CLAMP:
387                 case VERTEXATTRIBTYPE_NONPURE_SNORM32_CLAMP:
388                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP:
389                 case VERTEXATTRIBTYPE_NONPURE_SNORM8_SCALE:
390                 case VERTEXATTRIBTYPE_NONPURE_SNORM16_SCALE:
391                 case VERTEXATTRIBTYPE_NONPURE_SNORM32_SCALE:
392                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE:
393                 case VERTEXATTRIBTYPE_NONPURE_UINT8:
394                 case VERTEXATTRIBTYPE_NONPURE_UINT16:
395                 case VERTEXATTRIBTYPE_NONPURE_UINT32:
396                 case VERTEXATTRIBTYPE_NONPURE_INT8:
397                 case VERTEXATTRIBTYPE_NONPURE_INT16:
398                 case VERTEXATTRIBTYPE_NONPURE_INT32:
399                 case VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV:
400                 case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:
401                 case VERTEXATTRIBTYPE_PURE_INT8:
402                 case VERTEXATTRIBTYPE_PURE_INT16:
403                 case VERTEXATTRIBTYPE_PURE_INT32:
404                 case VERTEXATTRIBTYPE_NONPURE_UNORM8_BGRA:
405                 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA:
406                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:
407                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:
408                         DE_FATAL("Invalid read");
409
410                 default:
411                         DE_ASSERT(false);
412         }
413 }
414
415 int getComponentSize (const VertexAttribType type)
416 {
417         switch (type)
418         {
419                 case VERTEXATTRIBTYPE_FLOAT:                                                                    return 4;
420                 case VERTEXATTRIBTYPE_HALF:                                                                             return 2;
421                 case VERTEXATTRIBTYPE_FIXED:                                                                    return 4;
422                 case VERTEXATTRIBTYPE_DOUBLE:                                                                   return (int)sizeof(double);
423                 case VERTEXATTRIBTYPE_NONPURE_UNORM8:                                                   return 1;
424                 case VERTEXATTRIBTYPE_NONPURE_UNORM16:                                                  return 2;
425                 case VERTEXATTRIBTYPE_NONPURE_UNORM32:                                                  return 4;
426                 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV:                             return (int)sizeof(deUint32)/4;
427                 case VERTEXATTRIBTYPE_NONPURE_SNORM8_CLAMP:                                             return 1;
428                 case VERTEXATTRIBTYPE_NONPURE_SNORM16_CLAMP:                                    return 2;
429                 case VERTEXATTRIBTYPE_NONPURE_SNORM32_CLAMP:                                    return 4;
430                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP:               return (int)sizeof(deUint32)/4;
431                 case VERTEXATTRIBTYPE_NONPURE_SNORM8_SCALE:                                             return 1;
432                 case VERTEXATTRIBTYPE_NONPURE_SNORM16_SCALE:                                    return 2;
433                 case VERTEXATTRIBTYPE_NONPURE_SNORM32_SCALE:                                    return 4;
434                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE:               return (int)sizeof(deUint32)/4;
435                 case VERTEXATTRIBTYPE_NONPURE_UINT8:                                                    return 1;
436                 case VERTEXATTRIBTYPE_NONPURE_UINT16:                                                   return 2;
437                 case VERTEXATTRIBTYPE_NONPURE_UINT32:                                                   return 4;
438                 case VERTEXATTRIBTYPE_NONPURE_INT8:                                                             return 1;
439                 case VERTEXATTRIBTYPE_NONPURE_INT16:                                                    return 2;
440                 case VERTEXATTRIBTYPE_NONPURE_INT32:                                                    return 4;
441                 case VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV:                              return (int)sizeof(deUint32)/4;
442                 case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:                               return (int)sizeof(deUint32)/4;
443                 case VERTEXATTRIBTYPE_PURE_UINT8:                                                               return 1;
444                 case VERTEXATTRIBTYPE_PURE_UINT16:                                                              return 2;
445                 case VERTEXATTRIBTYPE_PURE_UINT32:                                                              return 4;
446                 case VERTEXATTRIBTYPE_PURE_INT8:                                                                return 1;
447                 case VERTEXATTRIBTYPE_PURE_INT16:                                                               return 2;
448                 case VERTEXATTRIBTYPE_PURE_INT32:                                                               return 4;
449                 case VERTEXATTRIBTYPE_NONPURE_UNORM8_BGRA:                                              return 1;
450                 case VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA:                return (int)sizeof(deUint32)/4;
451                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:  return (int)sizeof(deUint32)/4;
452                 case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:  return (int)sizeof(deUint32)/4;
453                 default:
454                         DE_ASSERT(false);
455                         return 0;
456         }
457 }
458
459 } // anonymous
460
461 bool isValidVertexAttrib (const VertexAttrib& vertexAttrib)
462 {
463         // Trivial range checks.
464         if (!de::inBounds<int>(vertexAttrib.type, 0, VERTEXATTRIBTYPE_LAST) ||
465                 !de::inRange(vertexAttrib.size, 0, 4) ||
466                 vertexAttrib.instanceDivisor < 0)
467                 return false;
468
469         // Generic attributes
470         if (!vertexAttrib.pointer && vertexAttrib.type != VERTEXATTRIBTYPE_DONT_CARE)
471                 return false;
472
473         // Packed formats
474         if ((vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV                           ||
475                  vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_UINT_2_10_10_10_REV                              ||
476                  vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV                             ||
477                  vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP               ||
478                  vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE               ||
479                  vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_UNORM_2_10_10_10_REV_BGRA                ||
480                  vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA  ||
481                  vertexAttrib.type == VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA) &&
482                 vertexAttrib.size != 4)
483                 return false;
484
485         return true;
486 }
487
488 void readVertexAttrib (tcu::Vec4& dst, const VertexAttrib& vertexAttrib, const int instanceNdx, const int vertexNdx)
489 {
490         DE_ASSERT(isValidVertexAttrib(vertexAttrib));
491
492         if (vertexAttrib.pointer)
493         {
494                 const int       elementNdx              = (vertexAttrib.instanceDivisor != 0) ? (instanceNdx / vertexAttrib.instanceDivisor) : vertexNdx;
495                 const int       compSize                = getComponentSize(vertexAttrib.type);
496                 const int       stride                  = (vertexAttrib.stride != 0) ? (vertexAttrib.stride) : (vertexAttrib.size*compSize);
497                 const int       byteOffset              = elementNdx*stride;
498
499                 dst = tcu::Vec4(0, 0, 0, 1); // defaults
500                 readFloat(dst, vertexAttrib.type, vertexAttrib.size, (const deUint8*)vertexAttrib.pointer + byteOffset);
501         }
502         else
503         {
504                 dst = vertexAttrib.generic.get<float>();
505         }
506 }
507
508 void readVertexAttrib (tcu::IVec4& dst, const VertexAttrib& vertexAttrib, const int instanceNdx, const int vertexNdx)
509 {
510         DE_ASSERT(isValidVertexAttrib(vertexAttrib));
511
512         if (vertexAttrib.pointer)
513         {
514                 const int       elementNdx              = (vertexAttrib.instanceDivisor != 0) ? (instanceNdx / vertexAttrib.instanceDivisor) : vertexNdx;
515                 const int       compSize                = getComponentSize(vertexAttrib.type);
516                 const int       stride                  = (vertexAttrib.stride != 0) ? (vertexAttrib.stride) : (vertexAttrib.size*compSize);
517                 const int       byteOffset              = elementNdx*stride;
518
519                 dst = tcu::IVec4(0, 0, 0, 1); // defaults
520                 readInt(dst, vertexAttrib.type, vertexAttrib.size, (const deUint8*)vertexAttrib.pointer + byteOffset);
521         }
522         else
523         {
524                 dst = vertexAttrib.generic.get<deInt32>();
525         }
526 }
527
528 void readVertexAttrib (tcu::UVec4& dst, const VertexAttrib& vertexAttrib, const int instanceNdx, const int vertexNdx)
529 {
530         DE_ASSERT(isValidVertexAttrib(vertexAttrib));
531
532         if (vertexAttrib.pointer)
533         {
534                 const int       elementNdx              = (vertexAttrib.instanceDivisor != 0) ? (instanceNdx / vertexAttrib.instanceDivisor) : vertexNdx;
535                 const int       compSize                = getComponentSize(vertexAttrib.type);
536                 const int       stride                  = (vertexAttrib.stride != 0) ? (vertexAttrib.stride) : (vertexAttrib.size*compSize);
537                 const int       byteOffset              = elementNdx*stride;
538
539                 dst = tcu::UVec4(0, 0, 0, 1); // defaults
540                 readUint(dst, vertexAttrib.type, vertexAttrib.size, (const deUint8*)vertexAttrib.pointer + byteOffset);
541         }
542         else
543         {
544                 dst = vertexAttrib.generic.get<deUint32>();
545         }
546 }
547
548 } // rr