Home | History | Annotate | Download | only in referencerenderer
      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] = aligned[0] / float(1 << 16);
    132 	if (size >= 2) dst[1] = aligned[1] / float(1 << 16);
    133 	if (size >= 3) dst[2] = aligned[2] / float(1 << 16);
    134 	if (size >= 4) dst[3] = 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_ASSERT(!"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_ASSERT(!"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_ASSERT(!"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 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 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 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 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 sizeof(deUint32)/4;
    442 		case VERTEXATTRIBTYPE_NONPURE_INT_2_10_10_10_REV:				return 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 sizeof(deUint32)/4;
    451 		case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:	return sizeof(deUint32)/4;
    452 		case VERTEXATTRIBTYPE_NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:	return 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
    549