Home | History | Annotate | Download | only in Shader
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "VertexRoutine.hpp"
     16 
     17 #include "VertexShader.hpp"
     18 #include "Vertex.hpp"
     19 #include "Half.hpp"
     20 #include "Renderer.hpp"
     21 #include "Constants.hpp"
     22 #include "Debug.hpp"
     23 
     24 namespace sw
     25 {
     26 	extern bool halfIntegerCoordinates;     // Pixel centers are not at integer coordinates
     27 	extern bool symmetricNormalizedDepth;   // [-1, 1] instead of [0, 1]
     28 
     29 	VertexRoutine::VertexRoutine(const VertexProcessor::State &state, const VertexShader *shader)
     30 		: v(shader && shader->dynamicallyIndexedInput),
     31 		  o(shader && shader->dynamicallyIndexedOutput),
     32 		  state(state)
     33 	{
     34 	}
     35 
     36 	VertexRoutine::~VertexRoutine()
     37 	{
     38 	}
     39 
     40 	void VertexRoutine::generate()
     41 	{
     42 		const bool textureSampling = state.textureSampling;
     43 
     44 		Pointer<Byte> cache = task + OFFSET(VertexTask,vertexCache);
     45 		Pointer<Byte> vertexCache = cache + OFFSET(VertexCache,vertex);
     46 		Pointer<Byte> tagCache = cache + OFFSET(VertexCache,tag);
     47 
     48 		UInt vertexCount = *Pointer<UInt>(task + OFFSET(VertexTask,vertexCount));
     49 		UInt primitiveNumber = *Pointer<UInt>(task + OFFSET(VertexTask, primitiveStart));
     50 		UInt indexInPrimitive = 0;
     51 
     52 		constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,constants));
     53 
     54 		Do
     55 		{
     56 			UInt index = *Pointer<UInt>(batch);
     57 			UInt tagIndex = index & 0x0000003C;
     58 			UInt indexQ = !textureSampling ? UInt(index & 0xFFFFFFFC) : index;   // FIXME: TEXLDL hack to have independent LODs, hurts performance.
     59 
     60 			If(*Pointer<UInt>(tagCache + tagIndex) != indexQ)
     61 			{
     62 				*Pointer<UInt>(tagCache + tagIndex) = indexQ;
     63 
     64 				readInput(indexQ);
     65 				pipeline(indexQ);
     66 				postTransform();
     67 				computeClipFlags();
     68 
     69 				Pointer<Byte> cacheLine0 = vertexCache + tagIndex * UInt((int)sizeof(Vertex));
     70 				writeCache(cacheLine0);
     71 			}
     72 
     73 			UInt cacheIndex = index & 0x0000003F;
     74 			Pointer<Byte> cacheLine = vertexCache + cacheIndex * UInt((int)sizeof(Vertex));
     75 			writeVertex(vertex, cacheLine);
     76 
     77 			if(state.transformFeedbackEnabled != 0)
     78 			{
     79 				transformFeedback(vertex, primitiveNumber, indexInPrimitive);
     80 
     81 				indexInPrimitive++;
     82 				If(indexInPrimitive == 3)
     83 				{
     84 					primitiveNumber++;
     85 					indexInPrimitive = 0;
     86 				}
     87 			}
     88 
     89 			vertex += sizeof(Vertex);
     90 			batch += sizeof(unsigned int);
     91 			vertexCount--;
     92 		}
     93 		Until(vertexCount == 0)
     94 
     95 		Return();
     96 	}
     97 
     98 	void VertexRoutine::readInput(UInt &index)
     99 	{
    100 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
    101 		{
    102 			Pointer<Byte> input = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,input) + sizeof(void*) * i);
    103 			UInt stride = *Pointer<UInt>(data + OFFSET(DrawData,stride) + sizeof(unsigned int) * i);
    104 
    105 			v[i] = readStream(input, stride, state.input[i], index);
    106 		}
    107 	}
    108 
    109 	void VertexRoutine::computeClipFlags()
    110 	{
    111 		int pos = state.positionRegister;
    112 
    113 		Int4 maxX = CmpLT(o[pos].w, o[pos].x);
    114 		Int4 maxY = CmpLT(o[pos].w, o[pos].y);
    115 		Int4 maxZ = CmpLT(o[pos].w, o[pos].z);
    116 		Int4 minX = CmpNLE(-o[pos].w, o[pos].x);
    117 		Int4 minY = CmpNLE(-o[pos].w, o[pos].y);
    118 		Int4 minZ = symmetricNormalizedDepth ? CmpNLE(-o[pos].w, o[pos].z) : CmpNLE(Float4(0.0f), o[pos].z);
    119 
    120 		clipFlags = *Pointer<Int>(constants + OFFSET(Constants,maxX) + SignMask(maxX) * 4);   // FIXME: Array indexing
    121 		clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,maxY) + SignMask(maxY) * 4);
    122 		clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,maxZ) + SignMask(maxZ) * 4);
    123 		clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minX) + SignMask(minX) * 4);
    124 		clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minY) + SignMask(minY) * 4);
    125 		clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minZ) + SignMask(minZ) * 4);
    126 
    127 		Int4 finiteX = CmpLE(Abs(o[pos].x), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
    128 		Int4 finiteY = CmpLE(Abs(o[pos].y), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
    129 		Int4 finiteZ = CmpLE(Abs(o[pos].z), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
    130 
    131 		Int4 finiteXYZ = finiteX & finiteY & finiteZ;
    132 		clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,fini) + SignMask(finiteXYZ) * 4);
    133 
    134 		if(state.preTransformed)
    135 		{
    136 			clipFlags &= 0xFBFBFBFB;   // Don't clip against far clip plane
    137 		}
    138 	}
    139 
    140 	Vector4f VertexRoutine::readStream(Pointer<Byte> &buffer, UInt &stride, const Stream &stream, const UInt &index)
    141 	{
    142 		const bool textureSampling = state.textureSampling;
    143 
    144 		Vector4f v;
    145 
    146 		Pointer<Byte> source0 = buffer + index * stride;
    147 		Pointer<Byte> source1 = source0 + (!textureSampling ? stride : 0);
    148 		Pointer<Byte> source2 = source1 + (!textureSampling ? stride : 0);
    149 		Pointer<Byte> source3 = source2 + (!textureSampling ? stride : 0);
    150 
    151 		bool isNativeFloatAttrib = (stream.attribType == VertexShader::ATTRIBTYPE_FLOAT) || stream.normalized;
    152 
    153 		switch(stream.type)
    154 		{
    155 		case STREAMTYPE_FLOAT:
    156 			{
    157 				if(stream.count == 0)
    158 				{
    159 					// Null stream, all default components
    160 				}
    161 				else
    162 				{
    163 					if(stream.count == 1)
    164 					{
    165 						v.x.x = *Pointer<Float>(source0);
    166 						v.x.y = *Pointer<Float>(source1);
    167 						v.x.z = *Pointer<Float>(source2);
    168 						v.x.w = *Pointer<Float>(source3);
    169 					}
    170 					else
    171 					{
    172 						v.x = *Pointer<Float4>(source0);
    173 						v.y = *Pointer<Float4>(source1);
    174 						v.z = *Pointer<Float4>(source2);
    175 						v.w = *Pointer<Float4>(source3);
    176 
    177 						transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    178 					}
    179 
    180 					switch(stream.attribType)
    181 					{
    182 					case VertexShader::ATTRIBTYPE_INT:
    183 						if(stream.count >= 1) v.x = As<Float4>(Int4(v.x));
    184 						if(stream.count >= 2) v.x = As<Float4>(Int4(v.y));
    185 						if(stream.count >= 3) v.x = As<Float4>(Int4(v.z));
    186 						if(stream.count >= 4) v.x = As<Float4>(Int4(v.w));
    187 						break;
    188 					case VertexShader::ATTRIBTYPE_UINT:
    189 						if(stream.count >= 1) v.x = As<Float4>(UInt4(v.x));
    190 						if(stream.count >= 2) v.x = As<Float4>(UInt4(v.y));
    191 						if(stream.count >= 3) v.x = As<Float4>(UInt4(v.z));
    192 						if(stream.count >= 4) v.x = As<Float4>(UInt4(v.w));
    193 						break;
    194 					default:
    195 						break;
    196 					}
    197 				}
    198 			}
    199 			break;
    200 		case STREAMTYPE_BYTE:
    201 			if(isNativeFloatAttrib) // Stream: UByte, Shader attrib: Float
    202 			{
    203 				v.x = Float4(*Pointer<Byte4>(source0));
    204 				v.y = Float4(*Pointer<Byte4>(source1));
    205 				v.z = Float4(*Pointer<Byte4>(source2));
    206 				v.w = Float4(*Pointer<Byte4>(source3));
    207 
    208 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    209 
    210 				if(stream.normalized)
    211 				{
    212 					if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
    213 					if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
    214 					if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
    215 					if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
    216 				}
    217 			}
    218 			else // Stream: UByte, Shader attrib: Int / UInt
    219 			{
    220 				v.x = As<Float4>(Int4(*Pointer<Byte4>(source0)));
    221 				v.y = As<Float4>(Int4(*Pointer<Byte4>(source1)));
    222 				v.z = As<Float4>(Int4(*Pointer<Byte4>(source2)));
    223 				v.w = As<Float4>(Int4(*Pointer<Byte4>(source3)));
    224 
    225 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    226 			}
    227 			break;
    228 		case STREAMTYPE_SBYTE:
    229 			if(isNativeFloatAttrib) // Stream: SByte, Shader attrib: Float
    230 			{
    231 				v.x = Float4(*Pointer<SByte4>(source0));
    232 				v.y = Float4(*Pointer<SByte4>(source1));
    233 				v.z = Float4(*Pointer<SByte4>(source2));
    234 				v.w = Float4(*Pointer<SByte4>(source3));
    235 
    236 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    237 
    238 				if(stream.normalized)
    239 				{
    240 					if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleSByte));
    241 					if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleSByte));
    242 					if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleSByte));
    243 					if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleSByte));
    244 				}
    245 			}
    246 			else // Stream: SByte, Shader attrib: Int / UInt
    247 			{
    248 				v.x = As<Float4>(Int4(*Pointer<SByte4>(source0)));
    249 				v.y = As<Float4>(Int4(*Pointer<SByte4>(source1)));
    250 				v.z = As<Float4>(Int4(*Pointer<SByte4>(source2)));
    251 				v.w = As<Float4>(Int4(*Pointer<SByte4>(source3)));
    252 
    253 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    254 			}
    255 			break;
    256 		case STREAMTYPE_COLOR:
    257 			{
    258 				v.x = Float4(*Pointer<Byte4>(source0)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
    259 				v.y = Float4(*Pointer<Byte4>(source1)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
    260 				v.z = Float4(*Pointer<Byte4>(source2)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
    261 				v.w = Float4(*Pointer<Byte4>(source3)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
    262 
    263 				transpose4x4(v.x, v.y, v.z, v.w);
    264 
    265 				// Swap red and blue
    266 				Float4 t = v.x;
    267 				v.x = v.z;
    268 				v.z = t;
    269 			}
    270 			break;
    271 		case STREAMTYPE_SHORT:
    272 			if(isNativeFloatAttrib) // Stream: Int, Shader attrib: Float
    273 			{
    274 				v.x = Float4(*Pointer<Short4>(source0));
    275 				v.y = Float4(*Pointer<Short4>(source1));
    276 				v.z = Float4(*Pointer<Short4>(source2));
    277 				v.w = Float4(*Pointer<Short4>(source3));
    278 
    279 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    280 
    281 				if(stream.normalized)
    282 				{
    283 					if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleShort));
    284 					if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleShort));
    285 					if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleShort));
    286 					if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleShort));
    287 				}
    288 			}
    289 			else // Stream: Short, Shader attrib: Int/UInt, no type conversion
    290 			{
    291 				v.x = As<Float4>(Int4(*Pointer<Short4>(source0)));
    292 				v.y = As<Float4>(Int4(*Pointer<Short4>(source1)));
    293 				v.z = As<Float4>(Int4(*Pointer<Short4>(source2)));
    294 				v.w = As<Float4>(Int4(*Pointer<Short4>(source3)));
    295 
    296 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    297 			}
    298 			break;
    299 		case STREAMTYPE_USHORT:
    300 			if(isNativeFloatAttrib) // Stream: Int, Shader attrib: Float
    301 			{
    302 				v.x = Float4(*Pointer<UShort4>(source0));
    303 				v.y = Float4(*Pointer<UShort4>(source1));
    304 				v.z = Float4(*Pointer<UShort4>(source2));
    305 				v.w = Float4(*Pointer<UShort4>(source3));
    306 
    307 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    308 
    309 				if(stream.normalized)
    310 				{
    311 					if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleUShort));
    312 					if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleUShort));
    313 					if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleUShort));
    314 					if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleUShort));
    315 				}
    316 			}
    317 			else // Stream: UShort, Shader attrib: Int/UInt, no type conversion
    318 			{
    319 				v.x = As<Float4>(Int4(*Pointer<UShort4>(source0)));
    320 				v.y = As<Float4>(Int4(*Pointer<UShort4>(source1)));
    321 				v.z = As<Float4>(Int4(*Pointer<UShort4>(source2)));
    322 				v.w = As<Float4>(Int4(*Pointer<UShort4>(source3)));
    323 
    324 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    325 			}
    326 			break;
    327 		case STREAMTYPE_INT:
    328 			if(isNativeFloatAttrib) // Stream: Int, Shader attrib: Float
    329 			{
    330 				v.x = Float4(*Pointer<Int4>(source0));
    331 				v.y = Float4(*Pointer<Int4>(source1));
    332 				v.z = Float4(*Pointer<Int4>(source2));
    333 				v.w = Float4(*Pointer<Int4>(source3));
    334 
    335 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    336 
    337 				if(stream.normalized)
    338 				{
    339 					if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleInt));
    340 					if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleInt));
    341 					if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleInt));
    342 					if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleInt));
    343 				}
    344 			}
    345 			else // Stream: Int, Shader attrib: Int/UInt, no type conversion
    346 			{
    347 				v.x = *Pointer<Float4>(source0);
    348 				v.y = *Pointer<Float4>(source1);
    349 				v.z = *Pointer<Float4>(source2);
    350 				v.w = *Pointer<Float4>(source3);
    351 
    352 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    353 			}
    354 			break;
    355 		case STREAMTYPE_UINT:
    356 			if(isNativeFloatAttrib) // Stream: UInt, Shader attrib: Float
    357 			{
    358 				v.x = Float4(*Pointer<UInt4>(source0));
    359 				v.y = Float4(*Pointer<UInt4>(source1));
    360 				v.z = Float4(*Pointer<UInt4>(source2));
    361 				v.w = Float4(*Pointer<UInt4>(source3));
    362 
    363 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    364 
    365 				if(stream.normalized)
    366 				{
    367 					if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleUInt));
    368 					if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleUInt));
    369 					if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleUInt));
    370 					if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleUInt));
    371 				}
    372 			}
    373 			else // Stream: UInt, Shader attrib: Int/UInt, no type conversion
    374 			{
    375 				v.x = *Pointer<Float4>(source0);
    376 				v.y = *Pointer<Float4>(source1);
    377 				v.z = *Pointer<Float4>(source2);
    378 				v.w = *Pointer<Float4>(source3);
    379 
    380 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    381 			}
    382 			break;
    383 		case STREAMTYPE_UDEC3:
    384 			{
    385 				// FIXME: Vectorize
    386 				{
    387 					Int x, y, z;
    388 
    389 					x = y = z = *Pointer<Int>(source0);
    390 
    391 					v.x.x = Float(x & 0x000003FF);
    392 					v.x.y = Float(y & 0x000FFC00);
    393 					v.x.z = Float(z & 0x3FF00000);
    394 				}
    395 
    396 				{
    397 					Int x, y, z;
    398 
    399 					x = y = z = *Pointer<Int>(source1);
    400 
    401 					v.y.x = Float(x & 0x000003FF);
    402 					v.y.y = Float(y & 0x000FFC00);
    403 					v.y.z = Float(z & 0x3FF00000);
    404 				}
    405 
    406 				{
    407 					Int x, y, z;
    408 
    409 					x = y = z = *Pointer<Int>(source2);
    410 
    411 					v.z.x = Float(x & 0x000003FF);
    412 					v.z.y = Float(y & 0x000FFC00);
    413 					v.z.z = Float(z & 0x3FF00000);
    414 				}
    415 
    416 				{
    417 					Int x, y, z;
    418 
    419 					x = y = z = *Pointer<Int>(source3);
    420 
    421 					v.w.x = Float(x & 0x000003FF);
    422 					v.w.y = Float(y & 0x000FFC00);
    423 					v.w.z = Float(z & 0x3FF00000);
    424 				}
    425 
    426 				transpose4x3(v.x, v.y, v.z, v.w);
    427 
    428 				v.y *= Float4(1.0f / 0x00000400);
    429 				v.z *= Float4(1.0f / 0x00100000);
    430 			}
    431 			break;
    432 		case STREAMTYPE_DEC3N:
    433 			{
    434 				// FIXME: Vectorize
    435 				{
    436 					Int x, y, z;
    437 
    438 					x = y = z = *Pointer<Int>(source0);
    439 
    440 					v.x.x = Float((x << 22) & 0xFFC00000);
    441 					v.x.y = Float((y << 12) & 0xFFC00000);
    442 					v.x.z = Float((z << 2)  & 0xFFC00000);
    443 				}
    444 
    445 				{
    446 					Int x, y, z;
    447 
    448 					x = y = z = *Pointer<Int>(source1);
    449 
    450 					v.y.x = Float((x << 22) & 0xFFC00000);
    451 					v.y.y = Float((y << 12) & 0xFFC00000);
    452 					v.y.z = Float((z << 2)  & 0xFFC00000);
    453 				}
    454 
    455 				{
    456 					Int x, y, z;
    457 
    458 					x = y = z = *Pointer<Int>(source2);
    459 
    460 					v.z.x = Float((x << 22) & 0xFFC00000);
    461 					v.z.y = Float((y << 12) & 0xFFC00000);
    462 					v.z.z = Float((z << 2)  & 0xFFC00000);
    463 				}
    464 
    465 				{
    466 					Int x, y, z;
    467 
    468 					x = y = z = *Pointer<Int>(source3);
    469 
    470 					v.w.x = Float((x << 22) & 0xFFC00000);
    471 					v.w.y = Float((y << 12) & 0xFFC00000);
    472 					v.w.z = Float((z << 2)  & 0xFFC00000);
    473 				}
    474 
    475 				transpose4x3(v.x, v.y, v.z, v.w);
    476 
    477 				v.x *= Float4(1.0f / 0x00400000 / 511.0f);
    478 				v.y *= Float4(1.0f / 0x00400000 / 511.0f);
    479 				v.z *= Float4(1.0f / 0x00400000 / 511.0f);
    480 			}
    481 			break;
    482 		case STREAMTYPE_FIXED:
    483 			{
    484 				v.x = Float4(*Pointer<Int4>(source0)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleFixed));
    485 				v.y = Float4(*Pointer<Int4>(source1)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleFixed));
    486 				v.z = Float4(*Pointer<Int4>(source2)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleFixed));
    487 				v.w = Float4(*Pointer<Int4>(source3)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleFixed));
    488 
    489 				transpose4xN(v.x, v.y, v.z, v.w, stream.count);
    490 			}
    491 			break;
    492 		case STREAMTYPE_HALF:
    493 			{
    494 				if(stream.count >= 1)
    495 				{
    496 					UShort x0 = *Pointer<UShort>(source0 + 0);
    497 					UShort x1 = *Pointer<UShort>(source1 + 0);
    498 					UShort x2 = *Pointer<UShort>(source2 + 0);
    499 					UShort x3 = *Pointer<UShort>(source3 + 0);
    500 
    501 					v.x.x = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(x0) * 4);
    502 					v.x.y = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(x1) * 4);
    503 					v.x.z = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(x2) * 4);
    504 					v.x.w = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(x3) * 4);
    505 				}
    506 
    507 				if(stream.count >= 2)
    508 				{
    509 					UShort y0 = *Pointer<UShort>(source0 + 2);
    510 					UShort y1 = *Pointer<UShort>(source1 + 2);
    511 					UShort y2 = *Pointer<UShort>(source2 + 2);
    512 					UShort y3 = *Pointer<UShort>(source3 + 2);
    513 
    514 					v.y.x = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(y0) * 4);
    515 					v.y.y = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(y1) * 4);
    516 					v.y.z = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(y2) * 4);
    517 					v.y.w = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(y3) * 4);
    518 				}
    519 
    520 				if(stream.count >= 3)
    521 				{
    522 					UShort z0 = *Pointer<UShort>(source0 + 4);
    523 					UShort z1 = *Pointer<UShort>(source1 + 4);
    524 					UShort z2 = *Pointer<UShort>(source2 + 4);
    525 					UShort z3 = *Pointer<UShort>(source3 + 4);
    526 
    527 					v.z.x = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(z0) * 4);
    528 					v.z.y = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(z1) * 4);
    529 					v.z.z = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(z2) * 4);
    530 					v.z.w = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(z3) * 4);
    531 				}
    532 
    533 				if(stream.count >= 4)
    534 				{
    535 					UShort w0 = *Pointer<UShort>(source0 + 6);
    536 					UShort w1 = *Pointer<UShort>(source1 + 6);
    537 					UShort w2 = *Pointer<UShort>(source2 + 6);
    538 					UShort w3 = *Pointer<UShort>(source3 + 6);
    539 
    540 					v.w.x = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(w0) * 4);
    541 					v.w.y = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(w1) * 4);
    542 					v.w.z = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(w2) * 4);
    543 					v.w.w = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(w3) * 4);
    544 				}
    545 			}
    546 			break;
    547 		case STREAMTYPE_INDICES:
    548 			{
    549 				v.x.x = *Pointer<Float>(source0);
    550 				v.x.y = *Pointer<Float>(source1);
    551 				v.x.z = *Pointer<Float>(source2);
    552 				v.x.w = *Pointer<Float>(source3);
    553 			}
    554 			break;
    555 		case STREAMTYPE_2_10_10_10_INT:
    556 			{
    557 				Int4 src;
    558 				src = Insert(src, *Pointer<Int>(source0), 0);
    559 				src = Insert(src, *Pointer<Int>(source1), 1);
    560 				src = Insert(src, *Pointer<Int>(source2), 2);
    561 				src = Insert(src, *Pointer<Int>(source3), 3);
    562 
    563 				v.x = Float4((src << 22) >> 22);
    564 				v.y = Float4((src << 12) >> 22);
    565 				v.z = Float4((src << 02) >> 22);
    566 				v.w = Float4(src >> 30);
    567 
    568 				if(stream.normalized)
    569 				{
    570 					v.x = Max(v.x * Float4(1.0f / 0x1FF), Float4(-1.0f));
    571 					v.y = Max(v.y * Float4(1.0f / 0x1FF), Float4(-1.0f));
    572 					v.z = Max(v.z * Float4(1.0f / 0x1FF), Float4(-1.0f));
    573 					v.w = Max(v.w, Float4(-1.0f));
    574 				}
    575 			}
    576 			break;
    577 		case STREAMTYPE_2_10_10_10_UINT:
    578 			{
    579 				Int4 src;
    580 				src = Insert(src, *Pointer<Int>(source0), 0);
    581 				src = Insert(src, *Pointer<Int>(source1), 1);
    582 				src = Insert(src, *Pointer<Int>(source2), 2);
    583 				src = Insert(src, *Pointer<Int>(source3), 3);
    584 
    585 				v.x = Float4(src & Int4(0x3FF));
    586 				v.y = Float4((src >> 10) & Int4(0x3FF));
    587 				v.z = Float4((src >> 20) & Int4(0x3FF));
    588 				v.w = Float4((src >> 30) & Int4(0x3));
    589 
    590 				if(stream.normalized)
    591 				{
    592 					v.x *= Float4(1.0f / 0x3FF);
    593 					v.y *= Float4(1.0f / 0x3FF);
    594 					v.z *= Float4(1.0f / 0x3FF);
    595 					v.w *= Float4(1.0f / 0x3);
    596 				}
    597 			}
    598 			break;
    599 		default:
    600 			ASSERT(false);
    601 		}
    602 
    603 		if(stream.count < 1) v.x = Float4(0.0f);
    604 		if(stream.count < 2) v.y = Float4(0.0f);
    605 		if(stream.count < 3) v.z = Float4(0.0f);
    606 		if(stream.count < 4) v.w = isNativeFloatAttrib ? As<Float4>(Float4(1.0f)) : As<Float4>(Int4(0));
    607 
    608 		return v;
    609 	}
    610 
    611 	void VertexRoutine::postTransform()
    612 	{
    613 		int pos = state.positionRegister;
    614 
    615 		// Backtransform
    616 		if(state.preTransformed)
    617 		{
    618 			Float4 rhw = Float4(1.0f) / o[pos].w;
    619 
    620 			Float4 W = *Pointer<Float4>(data + OFFSET(DrawData,Wx16)) * Float4(1.0f / 16.0f);
    621 			Float4 H = *Pointer<Float4>(data + OFFSET(DrawData,Hx16)) * Float4(1.0f / 16.0f);
    622 			Float4 L = *Pointer<Float4>(data + OFFSET(DrawData,X0x16)) * Float4(1.0f / 16.0f);
    623 			Float4 T = *Pointer<Float4>(data + OFFSET(DrawData,Y0x16)) * Float4(1.0f / 16.0f);
    624 
    625 			o[pos].x = (o[pos].x - L) / W * rhw;
    626 			o[pos].y = (o[pos].y - T) / H * rhw;
    627 			o[pos].z = o[pos].z * rhw;
    628 			o[pos].w = rhw;
    629 		}
    630 
    631 		if(!halfIntegerCoordinates && !state.preTransformed)
    632 		{
    633 			o[pos].x = o[pos].x + *Pointer<Float4>(data + OFFSET(DrawData,halfPixelX)) * o[pos].w;
    634 			o[pos].y = o[pos].y + *Pointer<Float4>(data + OFFSET(DrawData,halfPixelY)) * o[pos].w;
    635 		}
    636 
    637 		if(state.superSampling)
    638 		{
    639 			o[pos].x = o[pos].x + *Pointer<Float4>(data + OFFSET(DrawData,XXXX)) * o[pos].w;
    640 			o[pos].y = o[pos].y + *Pointer<Float4>(data + OFFSET(DrawData,YYYY)) * o[pos].w;
    641 		}
    642 	}
    643 
    644 	void VertexRoutine::writeCache(Pointer<Byte> &cacheLine)
    645 	{
    646 		Vector4f v;
    647 
    648 		for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
    649 		{
    650 			if(state.output[i].write)
    651 			{
    652 				v.x = o[i].x;
    653 				v.y = o[i].y;
    654 				v.z = o[i].z;
    655 				v.w = o[i].w;
    656 
    657 				if(state.output[i].xClamp)
    658 				{
    659 					v.x = Max(v.x, Float4(0.0f));
    660 					v.x = Min(v.x, Float4(1.0f));
    661 				}
    662 
    663 				if(state.output[i].yClamp)
    664 				{
    665 					v.y = Max(v.y, Float4(0.0f));
    666 					v.y = Min(v.y, Float4(1.0f));
    667 				}
    668 
    669 				if(state.output[i].zClamp)
    670 				{
    671 					v.z = Max(v.z, Float4(0.0f));
    672 					v.z = Min(v.z, Float4(1.0f));
    673 				}
    674 
    675 				if(state.output[i].wClamp)
    676 				{
    677 					v.w = Max(v.w, Float4(0.0f));
    678 					v.w = Min(v.w, Float4(1.0f));
    679 				}
    680 
    681 				if(state.output[i].write == 0x01)
    682 				{
    683 					*Pointer<Float>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 0) = v.x.x;
    684 					*Pointer<Float>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 1) = v.x.y;
    685 					*Pointer<Float>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 2) = v.x.z;
    686 					*Pointer<Float>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 3) = v.x.w;
    687 				}
    688 				else
    689 				{
    690 					if(state.output[i].write == 0x03)
    691 					{
    692 						transpose2x4(v.x, v.y, v.z, v.w);
    693 					}
    694 					else
    695 					{
    696 						transpose4x4(v.x, v.y, v.z, v.w);
    697 					}
    698 
    699 					*Pointer<Float4>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 0, 16) = v.x;
    700 					*Pointer<Float4>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 1, 16) = v.y;
    701 					*Pointer<Float4>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 2, 16) = v.z;
    702 					*Pointer<Float4>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 3, 16) = v.w;
    703 				}
    704 			}
    705 		}
    706 
    707 		*Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 0) = (clipFlags >> 0)  & 0x0000000FF;
    708 		*Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 1) = (clipFlags >> 8)  & 0x0000000FF;
    709 		*Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 2) = (clipFlags >> 16) & 0x0000000FF;
    710 		*Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 3) = (clipFlags >> 24) & 0x0000000FF;
    711 
    712 		// Viewport transform
    713 		int pos = state.positionRegister;
    714 
    715 		v.x = o[pos].x;
    716 		v.y = o[pos].y;
    717 		v.z = o[pos].z;
    718 		v.w = o[pos].w;
    719 
    720 		if(symmetricNormalizedDepth)
    721 		{
    722 			v.z = (v.z + v.w) * Float4(0.5f);   // [-1, 1] -> [0, 1]
    723 		}
    724 
    725 		Float4 w = As<Float4>(As<Int4>(v.w) | (As<Int4>(CmpEQ(v.w, Float4(0.0f))) & As<Int4>(Float4(1.0f))));
    726 		Float4 rhw = Float4(1.0f) / w;
    727 
    728 		v.x = As<Float4>(RoundInt(*Pointer<Float4>(data + OFFSET(DrawData,X0x16)) + v.x * rhw * *Pointer<Float4>(data + OFFSET(DrawData,Wx16))));
    729 		v.y = As<Float4>(RoundInt(*Pointer<Float4>(data + OFFSET(DrawData,Y0x16)) + v.y * rhw * *Pointer<Float4>(data + OFFSET(DrawData,Hx16))));
    730 		v.z = v.z * rhw;
    731 		v.w = rhw;
    732 
    733 		transpose4x4(v.x, v.y, v.z, v.w);
    734 
    735 		*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 0, 16) = v.x;
    736 		*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 1, 16) = v.y;
    737 		*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 2, 16) = v.z;
    738 		*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 3, 16) = v.w;
    739 	}
    740 
    741 	void VertexRoutine::writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cache)
    742 	{
    743 		for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
    744 		{
    745 			if(state.output[i].write)
    746 			{
    747 				*Pointer<Int4>(vertex + OFFSET(Vertex,v[i]), 16) = *Pointer<Int4>(cache + OFFSET(Vertex,v[i]), 16);
    748 			}
    749 		}
    750 
    751 		*Pointer<Int4>(vertex + OFFSET(Vertex,X)) = *Pointer<Int4>(cache + OFFSET(Vertex,X));
    752 		*Pointer<Int>(vertex + OFFSET(Vertex,clipFlags)) = *Pointer<Int>(cache + OFFSET(Vertex,clipFlags));
    753 	}
    754 
    755 	void VertexRoutine::transformFeedback(const Pointer<Byte> &vertex, const UInt &primitiveNumber, const UInt &indexInPrimitive)
    756 	{
    757 		If(indexInPrimitive < state.verticesPerPrimitive)
    758 		{
    759 			UInt tOffset = primitiveNumber * state.verticesPerPrimitive + indexInPrimitive;
    760 
    761 			for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
    762 			{
    763 				if(state.transformFeedbackEnabled & (1ULL << i))
    764 				{
    765 					UInt reg = *Pointer<UInt>(data + OFFSET(DrawData, vs.reg[i]));
    766 					UInt row = *Pointer<UInt>(data + OFFSET(DrawData, vs.row[i]));
    767 					UInt col = *Pointer<UInt>(data + OFFSET(DrawData, vs.col[i]));
    768 					UInt str = *Pointer<UInt>(data + OFFSET(DrawData, vs.str[i]));
    769 
    770 					Pointer<Byte> t = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.t[i])) + (tOffset * str * sizeof(float));
    771 					Pointer<Byte> v = vertex + OFFSET(Vertex, v) + reg * sizeof(float);
    772 
    773 					For(UInt r = 0, r < row, r++)
    774 					{
    775 						UInt rOffsetX = r * col * sizeof(float);
    776 						UInt rOffset4 = r * sizeof(float4);
    777 
    778 						For(UInt c = 0, c < col, c++)
    779 						{
    780 							UInt cOffset = c * sizeof(float);
    781 							*Pointer<Float>(t + rOffsetX + cOffset) = *Pointer<Float>(v + rOffset4 + cOffset);
    782 						}
    783 					}
    784 				}
    785 			}
    786 		}
    787 	}
    788 }
    789