VertexProgram.cpp revision c2534f4bc37baf48d9910d3691352ff83e3bea49
1894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// SwiftShader Software Renderer
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
3d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman// Copyright(c) 2005-2013 TransGaming Inc.
4894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
5894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// All rights reserved. No part of this software may be copied, distributed, transmitted,
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// transcribed, stored in a retrieval system, translated into any human or computer
7894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// language by any means, or disclosed to third parties without the explicit written
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// or implied, including but not limited to any patent rights, are granted to you.
10894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
11894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "VertexProgram.hpp"
13894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Renderer.hpp"
15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "VertexShader.hpp"
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Vertex.hpp"
17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Half.hpp"
18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "SamplerCore.hpp"
19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Debug.hpp"
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace sw
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
237551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens	VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader)
247551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		: VertexRoutine(state, shader), shader(shader), r(shader->dynamicallyIndexedTemporaries)
25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth = 0;
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth = 0;
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		breakDepth = 0;
2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		currentLabel = -1;
3019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		whileTest = false;
31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < 2048; i++)
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			labelBlock[i] = 0;
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
367551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens
377551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth = -1;
387551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
397551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens
407551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		if(shader && shader->containsBreakInstruction())
417551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		{
427551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
437551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		}
447551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens
457551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		if(shader && shader->containsContinueInstruction())
467551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		{
477551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableContinue = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
487551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		}
497551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens
507551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		if(shader->instanceIdDeclared)
517551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		{
527551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			instanceID = *Pointer<Int>(data + OFFSET(DrawData,instanceID));
537551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		}
54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	VertexProgram::~VertexProgram()
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
580b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu		for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			delete sampler[i];
61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
64b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::pipeline()
65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
660b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu		for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
687551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			sampler[i] = new SamplerCore(constants, state.samplerState[i]);
69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
71894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!state.preTransformed)
72894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
73b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			program();
74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
77b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			passThrough();
78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
80894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
81b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::program()
82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	//	shader->print("VertexShader-%0.8X.txt", state.shaderID);
84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
8519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		unsigned short version = shader->getVersion();
86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex = 0;
887551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		stackIndex = 0;
89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
904677a5f7a837e06dac90521eee0cf063cbfb9c9bNicolas Capens		if(shader->containsLeaveInstruction())
914677a5f7a837e06dac90521eee0cf063cbfb9c9bNicolas Capens		{
927551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableLeave = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
934677a5f7a837e06dac90521eee0cf063cbfb9c9bNicolas Capens		}
944677a5f7a837e06dac90521eee0cf063cbfb9c9bNicolas Capens
9519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		// Create all call site return blocks up front
96903e025f6cd8d978f013c741431b87b04ae01fd1Alexis Hetu		for(size_t i = 0; i < shader->getLength(); i++)
9719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
9819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			const Shader::Instruction *instruction = shader->getInstruction(i);
9919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Shader::Opcode opcode = instruction->opcode;
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(opcode == Shader::OPCODE_CALL || opcode == Shader::OPCODE_CALLNZ)
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				const Dst &dst = instruction->dst;
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				ASSERT(callRetBlock[dst.label].size() == dst.callSite);
10619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				callRetBlock[dst.label].push_back(Nucleus::createBasicBlock());
107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
109b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
110903e025f6cd8d978f013c741431b87b04ae01fd1Alexis Hetu		for(size_t i = 0; i < shader->getLength(); i++)
111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			const Shader::Instruction *instruction = shader->getInstruction(i);
11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Shader::Opcode opcode = instruction->opcode;
114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(opcode == Shader::OPCODE_DCL || opcode == Shader::OPCODE_DEF || opcode == Shader::OPCODE_DEFI || opcode == Shader::OPCODE_DEFB)
116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				continue;
118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Dst dst = instruction->dst;
12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Src src0 = instruction->src[0];
12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Src src1 = instruction->src[1];
12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Src src2 = instruction->src[2];
124c3d95f36258143af6cca041ede521995d8f890eaAlexis Hetu			Src src3 = instruction->src[3];
12525d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu			Src src4 = instruction->src[4];
126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			bool predicate = instruction->predicate;
12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Control control = instruction->control;
12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			bool integer = dst.type == Shader::PARAMETER_ADDR;
13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			bool pp = dst.partialPrecision;
131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f d;
13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f s0;
13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f s1;
13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Vector4f s2;
136c3d95f36258143af6cca041ede521995d8f890eaAlexis Hetu			Vector4f s3;
13725d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu			Vector4f s4;
138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
139c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
140c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
141c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
142c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegister(src3);
143c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegister(src4);
144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(opcode)
146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
147b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_VS_1_0:                                     break;
148b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_VS_1_1:                                     break;
149b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_VS_2_0:                                     break;
150b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_VS_2_x:                                     break;
151b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_VS_2_sw:                                    break;
152b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_VS_3_0:                                     break;
153b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_VS_3_sw:                                    break;
154b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DCL:                                        break;
155b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DEF:                                        break;
156b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DEFI:                                       break;
157b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DEFB:                                       break;
158b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NOP:                                        break;
159b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ABS:        abs(d, s0);                     break;
1600f4480780a2bfad69cece5fd9cabd1bf89f7393eAlexis Hetu			case Shader::OPCODE_IABS:       iabs(d, s0);                    break;
161b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ADD:        add(d, s0, s1);                 break;
1628d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IADD:       iadd(d, s0, s1);                break;
163b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CRS:        crs(d, s0, s1);                 break;
164b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FORWARD1:   forward1(d, s0, s1, s2);        break;
165b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FORWARD2:   forward2(d, s0, s1, s2);        break;
166b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FORWARD3:   forward3(d, s0, s1, s2);        break;
167b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FORWARD4:   forward4(d, s0, s1, s2);        break;
168b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFLECT1:   reflect1(d, s0, s1);            break;
169b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFLECT2:   reflect2(d, s0, s1);            break;
170b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFLECT3:   reflect3(d, s0, s1);            break;
171b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFLECT4:   reflect4(d, s0, s1);            break;
172b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFRACT1:   refract1(d, s0, s1, s2.x);      break;
173b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFRACT2:   refract2(d, s0, s1, s2.x);      break;
174b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFRACT3:   refract3(d, s0, s1, s2.x);      break;
175b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFRACT4:   refract4(d, s0, s1, s2.x);      break;
176b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DP1:        dp1(d, s0, s1);                 break;
177b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DP2:        dp2(d, s0, s1);                 break;
178b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DP3:        dp3(d, s0, s1);                 break;
179b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DP4:        dp4(d, s0, s1);                 break;
180c3d95f36258143af6cca041ede521995d8f890eaAlexis Hetu			case Shader::OPCODE_DET2:       det2(d, s0, s1);                break;
181c3d95f36258143af6cca041ede521995d8f890eaAlexis Hetu			case Shader::OPCODE_DET3:       det3(d, s0, s1, s2);            break;
182c3d95f36258143af6cca041ede521995d8f890eaAlexis Hetu			case Shader::OPCODE_DET4:       det4(d, s0, s1, s2, s3);        break;
183b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ATT:        att(d, s0, s1);                 break;
184b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXP2X:      exp2x(d, s0, pp);               break;
185b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXP2:       exp2(d, s0, pp);                break;
186b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXPP:       expp(d, s0, version);           break;
187b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXP:        exp(d, s0, pp);                 break;
188b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FRC:        frc(d, s0);                     break;
18919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			case Shader::OPCODE_TRUNC:      trunc(d, s0);                   break;
19019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			case Shader::OPCODE_FLOOR:      floor(d, s0);                   break;
191af1970ce7685ea66dd02ac462d6f2723d6f6e500Alexis Hetu			case Shader::OPCODE_ROUND:      round(d, s0);                   break;
192b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ROUNDEVEN:  roundEven(d, s0);               break;
19319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			case Shader::OPCODE_CEIL:       ceil(d, s0);                    break;
194b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LIT:        lit(d, s0);                     break;
195b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOG2X:      log2x(d, s0, pp);               break;
196b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOG2:       log2(d, s0, pp);                break;
197b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOGP:       logp(d, s0, version);           break;
198b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOG:        log(d, s0, pp);                 break;
199b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LRP:        lrp(d, s0, s1, s2);             break;
200b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_STEP:       step(d, s0, s1);                break;
201b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SMOOTH:     smooth(d, s0, s1, s2);          break;
2028d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_FLOATBITSTOINT:
2038d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_FLOATBITSTOUINT:
2048d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_INTBITSTOFLOAT:
2058d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UINTBITSTOFLOAT: d = s0;                    break;
206b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M3X2:       M3X2(d, s0, src1);              break;
207b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M3X3:       M3X3(d, s0, src1);              break;
208b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M3X4:       M3X4(d, s0, src1);              break;
209b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M4X3:       M4X3(d, s0, src1);              break;
210b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M4X4:       M4X4(d, s0, src1);              break;
211b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MAD:        mad(d, s0, s1, s2);             break;
212b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_IMAD:       imad(d, s0, s1, s2);            break;
213b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MAX:        max(d, s0, s1);                 break;
2148d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IMAX:       imax(d, s0, s1);                break;
2158d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UMAX:       umax(d, s0, s1);                break;
216b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MIN:        min(d, s0, s1);                 break;
2178d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IMIN:       imin(d, s0, s1);                break;
2188d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UMIN:       umin(d, s0, s1);                break;
219b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MOV:        mov(d, s0, integer);            break;
22002a2bb807c1e947bc99d68ba7dd4984289278be0Alexis Hetu			case Shader::OPCODE_MOVA:       mov(d, s0, true);               break;
2218d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_NEG:        neg(d, s0);                     break;
2228d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_INEG:       ineg(d, s0);                    break;
223b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_F2B:        f2b(d, s0);                     break;
224b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_B2F:        b2f(d, s0);                     break;
2258d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_F2I:        f2i(d, s0);                     break;
2268d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_I2F:        i2f(d, s0);                     break;
2278d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_F2U:        f2u(d, s0);                     break;
2288d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_U2F:        u2f(d, s0);                     break;
2298d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_I2B:        i2b(d, s0);                     break;
2308d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_B2I:        b2i(d, s0);                     break;
231b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MUL:        mul(d, s0, s1);                 break;
2328d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IMUL:       imul(d, s0, s1);                break;
233b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NRM2:       nrm2(d, s0, pp);                break;
234b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NRM3:       nrm3(d, s0, pp);                break;
235b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NRM4:       nrm4(d, s0, pp);                break;
236b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_POWX:       powx(d, s0, s1, pp);            break;
237b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_POW:        pow(d, s0, s1, pp);             break;
238b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_RCPX:       rcpx(d, s0, pp);                break;
239b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIV:        div(d, s0, s1);                 break;
2408d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IDIV:       idiv(d, s0, s1);                break;
2418d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UDIV:       udiv(d, s0, s1);                break;
242b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MOD:        mod(d, s0, s1);                 break;
2438d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IMOD:       imod(d, s0, s1);                break;
2448d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UMOD:       umod(d, s0, s1);                break;
2458d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_SHL:        shl(d, s0, s1);                 break;
246b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ISHR:       ishr(d, s0, s1);                break;
247b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_USHR:       ushr(d, s0, s1);                break;
248b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_RSQX:       rsqx(d, s0, pp);                break;
249b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SQRT:       sqrt(d, s0, pp);                break;
250b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_RSQ:        rsq(d, s0, pp);                 break;
251b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LEN2:       len2(d.x, s0, pp);              break;
252b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LEN3:       len3(d.x, s0, pp);              break;
253b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LEN4:       len4(d.x, s0, pp);              break;
254b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIST1:      dist1(d.x, s0, s1, pp);         break;
255b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIST2:      dist2(d.x, s0, s1, pp);         break;
256b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIST3:      dist3(d.x, s0, s1, pp);         break;
257b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIST4:      dist4(d.x, s0, s1, pp);         break;
258b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SGE:        step(d, s1, s0);                break;
259b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SGN:        sgn(d, s0);                     break;
2600f4480780a2bfad69cece5fd9cabd1bf89f7393eAlexis Hetu			case Shader::OPCODE_ISGN:       isgn(d, s0);                    break;
261b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SINCOS:     sincos(d, s0, pp);              break;
262b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_COS:        cos(d, s0, pp);                 break;
263b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SIN:        sin(d, s0, pp);                 break;
264b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TAN:        tan(d, s0);                     break;
265b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ACOS:       acos(d, s0);                    break;
266b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ASIN:       asin(d, s0);                    break;
267b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ATAN:       atan(d, s0);                    break;
268b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ATAN2:      atan2(d, s0, s1);               break;
269b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_COSH:       cosh(d, s0, pp);                break;
270b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SINH:       sinh(d, s0, pp);                break;
271b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TANH:       tanh(d, s0, pp);                break;
272b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ACOSH:      acosh(d, s0, pp);               break;
273b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ASINH:      asinh(d, s0, pp);               break;
274b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ATANH:      atanh(d, s0, pp);               break;
275b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SLT:        slt(d, s0, s1);                 break;
276b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SUB:        sub(d, s0, s1);                 break;
2778d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_ISUB:       isub(d, s0, s1);                break;
278b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_BREAK:      BREAK();                        break;
279b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_BREAKC:     BREAKC(s0, s1, control);        break;
280b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_BREAKP:     BREAKP(src0);                   break;
281b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CONTINUE:   CONTINUE();                     break;
282b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEST:       TEST();                         break;
283b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CALL:       CALL(dst.label, dst.callSite);  break;
284b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CALLNZ:     CALLNZ(dst.label, dst.callSite, src0); break;
285b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ELSE:       ELSE();                         break;
286b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ENDIF:      ENDIF();                        break;
287b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ENDLOOP:    ENDLOOP();                      break;
288b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ENDREP:     ENDREP();                       break;
289b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ENDWHILE:   ENDWHILE();                     break;
290b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_IF:         IF(src0);                       break;
291b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_IFC:        IFC(s0, s1, control);           break;
292b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LABEL:      LABEL(dst.index);               break;
293b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOOP:       LOOP(src1);                     break;
294b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REP:        REP(src0);                      break;
295b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_WHILE:      WHILE(src0);                    break;
296b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_RET:        RET();                          break;
297b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LEAVE:      LEAVE();                        break;
298b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CMP:        cmp(d, s0, s1, control);        break;
299b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ICMP:       icmp(d, s0, s1, control);       break;
3008d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UCMP:       ucmp(d, s0, s1, control);       break;
301b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SELECT:     select(d, s0, s1, s2);          break;
302b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXTRACT:    extract(d.x, s0, s1.x);         break;
303b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_INSERT:     insert(d, s0, s1.x, s2.x);      break;
304b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ALL:        all(d.x, s0);                   break;
305b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ANY:        any(d.x, s0);                   break;
306b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NOT:        not(d, s0);                     break;
3078d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_OR:         or(d, s0, s1);                  break;
3088d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_XOR:        xor(d, s0, s1);                 break;
3098d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_AND:        and(d, s0, s1);                 break;
3108d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_EQ:         equal(d, s0, s1);               break;
3118d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_NE:         notEqual(d, s0, s1);            break;
312b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXLDL:     TEXLDL(d, s0, src1);            break;
313b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEX:        TEX(d, s0, src1);               break;
314b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXOFFSET:  TEXOFFSET(d, s0, src1, s2, s3); break;
315b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXLDLOFFSET: TEXLDL(d, s0, src1, s2);      break;
316b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXELFETCH: TEXELFETCH(d, s0, src1, s2);    break;
317b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCH(d, s0, src1, s2, s3); break;
318b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXGRAD:    TEXGRAD(d, s0, src1, s2, s3);   break;
319b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXGRADOFFSET: TEXGRAD(d, s0, src1, s2, s3, s4); break;
320b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXSIZE:    TEXSIZE(d, s0.x, src1);         break;
321b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_END:                                        break;
322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			default:
323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				ASSERT(false);
324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
32619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(dst.type != Shader::PARAMETER_VOID && dst.type != Shader::PARAMETER_LABEL && opcode != Shader::OPCODE_NOP)
327894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
32819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(dst.integer)
32919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
33019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					switch(opcode)
33119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
33219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::OPCODE_DIV:
33319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.x) d.x = Trunc(d.x);
33419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.y) d.y = Trunc(d.y);
33519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.z) d.z = Trunc(d.z);
33619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.w) d.w = Trunc(d.w);
33719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						break;
33819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					default:
33919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						break;   // No truncation to integer required when arguments are integer
34019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
34119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
34219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
34319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(dst.saturate)
344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
34519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.x) d.x = Max(d.x, Float4(0.0f));
34619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.y) d.y = Max(d.y, Float4(0.0f));
34719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.z) d.z = Max(d.z, Float4(0.0f));
34819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.w) d.w = Max(d.w, Float4(0.0f));
34919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
35019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.x) d.x = Min(d.x, Float4(1.0f));
35119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.y) d.y = Min(d.y, Float4(1.0f));
35219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.z) d.z = Min(d.z, Float4(1.0f));
35319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.w) d.w = Min(d.w, Float4(1.0f));
354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
356c6e8ab13ecf20217229de8f4f19a14bbc18778f9Nicolas Capens				if(instruction->isPredicated())
357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
35819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f pDst;   // FIXME: Rename
359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
36019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					switch(dst.type)
361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
362b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens					case Shader::PARAMETER_VOID: break;
36319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::PARAMETER_TEMP:
36419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.rel.type == Shader::PARAMETER_VOID)
36519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						{
3667551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) pDst.x = r[dst.index].x;
3677551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) pDst.y = r[dst.index].y;
3687551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) pDst.z = r[dst.index].z;
3697551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) pDst.w = r[dst.index].w;
37019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						}
37119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						else
37219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						{
373b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens							Int a = relativeAddress(dst);
37419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
3757551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) pDst.x = r[dst.index + a].x;
3767551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) pDst.y = r[dst.index + a].y;
3777551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) pDst.z = r[dst.index + a].z;
3787551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) pDst.w = r[dst.index + a].w;
37919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						}
38019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						break;
3817551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					case Shader::PARAMETER_ADDR: pDst = a0; break;
38219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::PARAMETER_RASTOUT:
38319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						switch(dst.index)
384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 0:
3867551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) pDst.x = o[Pos].x;
3877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) pDst.y = o[Pos].y;
3887551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) pDst.z = o[Pos].z;
3897551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) pDst.w = o[Pos].w;
390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 1:
3927551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							pDst.x = o[Fog].x;
393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 2:
3957551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							pDst.x = o[Pts].y;
396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						default:
398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							ASSERT(false);
399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
40119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::PARAMETER_ATTROUT:
4027551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) pDst.x = o[D0 + dst.index].x;
4037551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) pDst.y = o[D0 + dst.index].y;
4047551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) pDst.z = o[D0 + dst.index].z;
4057551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) pDst.w = o[D0 + dst.index].w;
406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
40719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::PARAMETER_TEXCRDOUT:
40819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				//	case Shader::PARAMETER_OUTPUT:
409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						if(version < 0x0300)
410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
4117551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) pDst.x = o[T0 + dst.index].x;
4127551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) pDst.y = o[T0 + dst.index].y;
4137551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) pDst.z = o[T0 + dst.index].z;
4147551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) pDst.w = o[T0 + dst.index].w;
415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						else
417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
41819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.rel.type == Shader::PARAMETER_VOID)   // Not relative
419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							{
4207551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.x) pDst.x = o[dst.index].x;
4217551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.y) pDst.y = o[dst.index].y;
4227551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.z) pDst.z = o[dst.index].z;
4237551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.w) pDst.w = o[dst.index].w;
424894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							}
42519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							else
42619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							{
427b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens								Int a = relativeAddress(dst);
42819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
4297551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.x) pDst.x = o[dst.index + a].x;
4307551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.y) pDst.y = o[dst.index + a].y;
4317551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.z) pDst.z = o[dst.index + a].z;
4327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.w) pDst.w = o[dst.index + a].w;
433894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							}
434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
4367551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					case Shader::PARAMETER_LABEL:                break;
4377551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					case Shader::PARAMETER_PREDICATE: pDst = p0; break;
4387551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					case Shader::PARAMETER_INPUT:                break;
439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					default:
440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						ASSERT(false);
441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
443b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens					Int4 enable = enableMask(instruction);
444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
445894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Int4 xEnable = enable;
446894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Int4 yEnable = enable;
447894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Int4 zEnable = enable;
448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Int4 wEnable = enable;
449894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(predicate)
451894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
45219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						unsigned char pSwizzle = instruction->predicateSwizzle;
453894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4547551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 xPredicate = p0[(pSwizzle >> 0) & 0x03];
4557551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 yPredicate = p0[(pSwizzle >> 2) & 0x03];
4567551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 zPredicate = p0[(pSwizzle >> 4) & 0x03];
4577551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 wPredicate = p0[(pSwizzle >> 6) & 0x03];
458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
45919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(!instruction->predicateNot)
460894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
46119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.x) xEnable = xEnable & As<Int4>(xPredicate);
46219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.y) yEnable = yEnable & As<Int4>(yPredicate);
46319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.z) zEnable = zEnable & As<Int4>(zPredicate);
46419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.w) wEnable = wEnable & As<Int4>(wPredicate);
465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
466894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						else
467894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
46819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.x) xEnable = xEnable & ~As<Int4>(xPredicate);
46919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.y) yEnable = yEnable & ~As<Int4>(yPredicate);
47019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.z) zEnable = zEnable & ~As<Int4>(zPredicate);
47119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.w) wEnable = wEnable & ~As<Int4>(wPredicate);
472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
473894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
47519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.x) d.x = As<Float4>(As<Int4>(d.x) & xEnable);
47619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.y) d.y = As<Float4>(As<Int4>(d.y) & yEnable);
47719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.z) d.z = As<Float4>(As<Int4>(d.z) & zEnable);
47819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.w) d.w = As<Float4>(As<Int4>(d.w) & wEnable);
479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
48019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.x) d.x = As<Float4>(As<Int4>(d.x) | (As<Int4>(pDst.x) & ~xEnable));
48119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.y) d.y = As<Float4>(As<Int4>(d.y) | (As<Int4>(pDst.y) & ~yEnable));
48219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.z) d.z = As<Float4>(As<Int4>(d.z) | (As<Int4>(pDst.z) & ~zEnable));
48319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.w) d.w = As<Float4>(As<Int4>(d.w) | (As<Int4>(pDst.w) & ~wEnable));
484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
48619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				switch(dst.type)
487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
48819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_VOID:
489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
49019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_TEMP:
49119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.rel.type == Shader::PARAMETER_VOID)
49219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
4937551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) r[dst.index].x = d.x;
4947551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) r[dst.index].y = d.y;
4957551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) r[dst.index].z = d.z;
4967551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) r[dst.index].w = d.w;
49719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
49819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					else
49919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
500b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens						Int a = relativeAddress(dst);
50119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
5027551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) r[dst.index + a].x = d.x;
5037551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) r[dst.index + a].y = d.y;
5047551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) r[dst.index + a].z = d.z;
5057551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) r[dst.index + a].w = d.w;
50619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
507894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
50819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_ADDR:
5097551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.x) a0.x = d.x;
5107551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.y) a0.y = d.y;
5117551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.z) a0.z = d.z;
5127551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.w) a0.w = d.w;
513894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
51419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_RASTOUT:
51519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					switch(dst.index)
516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
517894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					case 0:
5187551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) o[Pos].x = d.x;
5197551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) o[Pos].y = d.y;
5207551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) o[Pos].z = d.z;
5217551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) o[Pos].w = d.w;
522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					case 1:
5247551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						o[Fog].x = d.x;
525894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
526b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens					case 2:
5277551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						o[Pts].y = d.x;
528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					default:	ASSERT(false);
530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
532b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens				case Shader::PARAMETER_ATTROUT:
5337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.x) o[D0 + dst.index].x = d.x;
5347551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.y) o[D0 + dst.index].y = d.y;
5357551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.z) o[D0 + dst.index].z = d.z;
5367551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.w) o[D0 + dst.index].w = d.w;
537894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
53819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_TEXCRDOUT:
53919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			//	case Shader::PARAMETER_OUTPUT:
540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(version < 0x0300)
541894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
5427551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) o[T0 + dst.index].x = d.x;
5437551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) o[T0 + dst.index].y = d.y;
5447551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) o[T0 + dst.index].z = d.z;
5457551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) o[T0 + dst.index].w = d.w;
546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else
548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
54919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.rel.type == Shader::PARAMETER_VOID)   // Not relative
550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
5517551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) o[dst.index].x = d.x;
5527551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) o[dst.index].y = d.y;
5537551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) o[dst.index].z = d.z;
5547551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) o[dst.index].w = d.w;
555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
55619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						else
55719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						{
558b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens							Int a = relativeAddress(dst);
55919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
5607551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) o[dst.index + a].x = d.x;
5617551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) o[dst.index + a].y = d.y;
5627551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) o[dst.index + a].z = d.z;
5637551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) o[dst.index + a].w = d.w;
564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
565894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
566894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
5677551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_LABEL:             break;
5687551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_PREDICATE: p0 = d; break;
5697551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_INPUT:             break;
570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				default:
571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					ASSERT(false);
572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
57619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(currentLabel != -1)
577894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
578894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::setInsertBlock(returnBlock);
579894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
582b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::passThrough()
583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
58419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(shader)
585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < 12; i++)
587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
58819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				unsigned char usage = shader->output[i][0].usage;
589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				switch(usage)
591894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				case 0xFF:
593894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					continue;
59419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_PSIZE:
5957551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].y = v[i].x;
596894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
59719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_TEXCOORD:
5987551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].x = v[i].x;
5997551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].y = v[i].y;
6007551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].z = v[i].z;
6017551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].w = v[i].w;
602894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
60319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_POSITION:
6047551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].x = v[i].x;
6057551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].y = v[i].y;
6067551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].z = v[i].z;
6077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].w = v[i].w;
608894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
60919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_COLOR:
6107551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].x = v[i].x;
6117551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].y = v[i].y;
6127551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].z = v[i].z;
6137551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].w = v[i].w;
614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
61519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_FOG:
6167551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].x = v[i].x;
617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
618894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				default:
619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					ASSERT(false);
620894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
622894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
623894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
624894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
6257551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pos].x = v[PositionT].x;
6267551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pos].y = v[PositionT].y;
6277551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pos].z = v[PositionT].z;
6287551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pos].w = v[PositionT].w;
629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
630894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < 2; i++)
631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
6327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[D0 + i].x = v[Color0 + i].x;
6337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[D0 + i].y = v[Color0 + i].y;
6347551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[D0 + i].z = v[Color0 + i].z;
6357551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[D0 + i].w = v[Color0 + i].w;
636894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
638894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < 8; i++)
639894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
6407551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + i].x = v[TexCoord0 + i].x;
6417551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + i].y = v[TexCoord0 + i].y;
6427551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + i].z = v[TexCoord0 + i].z;
6437551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + i].w = v[TexCoord0 + i].w;
644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
645894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
6467551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pts].y = v[PointSize].x;
647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
648894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
650c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens	Vector4f VertexProgram::fetchRegister(const Src &src, unsigned int offset)
651894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
65219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f reg;
6535d96188b9c35bf896c25755e4eb97d09dcf3bed7Nicolas Capens		unsigned int i = src.index + offset;
654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
655894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(src.type)
656894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
65719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_TEMP:
65819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(src.rel.type == Shader::PARAMETER_VOID)
65919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6607551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = r[i];
66119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
66219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else
66319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6642c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				reg = r[i + relativeAddress(src, src.bufferIndex)];
66519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
66619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			break;
66719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_CONST:
668b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			reg = readConstant(src, offset);
66919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			break;
67019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_INPUT:
67119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman            if(src.rel.type == Shader::PARAMETER_VOID)
67219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6737551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = v[i];
67419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
67519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else
67619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6772c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				reg = v[i + relativeAddress(src, src.bufferIndex)];
67819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
67919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman            break;
6807551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_VOID: return r[0];   // Dummy
68119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_FLOAT4LITERAL:
68219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			reg.x = Float4(src.value[0]);
68319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			reg.y = Float4(src.value[1]);
68419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			reg.z = Float4(src.value[2]);
68519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			reg.w = Float4(src.value[3]);
68619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			break;
6877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_ADDR:      reg = a0; break;
6887551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_CONSTBOOL: return r[0];   // Dummy
6897551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_CONSTINT:  return r[0];   // Dummy
6907551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_LOOP:      return r[0];   // Dummy
6917551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_PREDICATE: return r[0];   // Dummy
69219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_SAMPLER:
69319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(src.rel.type == Shader::PARAMETER_VOID)
69419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
69519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				reg.x = As<Float4>(Int4(i));
69619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
69719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else if(src.rel.type == Shader::PARAMETER_TEMP)
69819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6997551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg.x = As<Float4>(Int4(i) + As<Int4>(r[src.rel.index].x));
70019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
70119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			return reg;
70219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_OUTPUT:
70319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman            if(src.rel.type == Shader::PARAMETER_VOID)
70419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
7057551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = o[i];
70619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
70719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else
70819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
7092c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				reg = o[i + relativeAddress(src, src.bufferIndex)];
71019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
71119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			break;
712dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu		case Shader::PARAMETER_MISCTYPE:
7137551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			reg.x = As<Float>(Int(instanceID));
714dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu			return reg;
715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
717894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
718894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
71966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		const Float4 &x = reg[(src.swizzle >> 0) & 0x3];
72066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		const Float4 &y = reg[(src.swizzle >> 2) & 0x3];
72166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		const Float4 &z = reg[(src.swizzle >> 4) & 0x3];
72266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		const Float4 &w = reg[(src.swizzle >> 6) & 0x3];
723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
72466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		Vector4f mod;
725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
726894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(src.modifier)
727894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
72819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_NONE:
72966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = x;
73066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = y;
73166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = z;
73266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = w;
733894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
73419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_NEGATE:
73566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = -x;
73666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = -y;
73766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = -z;
73866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = -w;
739894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
74019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_ABS:
74166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = Abs(x);
74266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = Abs(y);
74366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = Abs(z);
74466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = Abs(w);
745894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
74619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_ABS_NEGATE:
74766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = -Abs(x);
74866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = -Abs(y);
74966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = -Abs(z);
75066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = -Abs(w);
751894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
75219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_NOT:
75366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = As<Float4>(As<Int4>(x) ^ Int4(0xFFFFFFFF));
75466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = As<Float4>(As<Int4>(y) ^ Int4(0xFFFFFFFF));
75566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = As<Float4>(As<Int4>(z) ^ Int4(0xFFFFFFFF));
75666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = As<Float4>(As<Int4>(w) ^ Int4(0xFFFFFFFF));
757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
758894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
759894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return mod;
763894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
7652c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu	RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index)
7662c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu	{
7672c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu		if(bufferIndex == -1)
7682c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu		{
7692c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu			return data + OFFSET(DrawData, vs.c[index]);
7702c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu		}
7712c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu		else
7722c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu		{
7732c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu			return *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.u[bufferIndex])) + index;
7742c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu		}
7752c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu	}
7762c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu
7772c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu	RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index, Int& offset)
7782c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu	{
7792c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu		return uniformAddress(bufferIndex, index) + offset * sizeof(float4);
7802c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu	}
7812c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu
782b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	Vector4f VertexProgram::readConstant(const Src &src, unsigned int offset)
783894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
78419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f c;
7855d96188b9c35bf896c25755e4eb97d09dcf3bed7Nicolas Capens		unsigned int i = src.index + offset;
78619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
78719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(src.rel.type == Shader::PARAMETER_VOID)   // Not relative
78819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
7892c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu			c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i));
79019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
79119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.x = c.x.xxxx;
79219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.y = c.y.yyyy;
79319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.z = c.z.zzzz;
79419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.w = c.w.wwww;
79519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
796eafdb22c36f2077815eadf2a1db0fb6547bf0241Nicolas Capens			if(shader->containsDefineInstruction())   // Constant may be known at compile time
79719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
798903e025f6cd8d978f013c741431b87b04ae01fd1Alexis Hetu				for(size_t j = 0; j < shader->getLength(); j++)
79919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
80019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					const Shader::Instruction &instruction = *shader->getInstruction(j);
80119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
80219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(instruction.opcode == Shader::OPCODE_DEF)
80319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
80419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(instruction.dst.index == i)
80519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						{
80619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							c.x = Float4(instruction.src[0].value[0]);
80719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							c.y = Float4(instruction.src[0].value[1]);
80819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							c.z = Float4(instruction.src[0].value[2]);
80919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							c.w = Float4(instruction.src[0].value[3]);
81019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
81119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							break;
81219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						}
81319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
81419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
81519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
81619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
81719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(src.rel.type == Shader::PARAMETER_LOOP)
81819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8197551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Int loopCounter = aL[loopDepth];
82019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8212c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu			c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, loopCounter));
82219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
82319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.x = c.x.xxxx;
82419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.y = c.y.yyyy;
82519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.z = c.z.zzzz;
82619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.w = c.w.wwww;
82719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
82819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else
82919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
83019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(src.rel.deterministic)
83119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
8322c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				Int a = relativeAddress(src, src.bufferIndex);
833c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens
8342c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, a));
835b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
83619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				c.x = c.x.xxxx;
83719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				c.y = c.y.yyyy;
83819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				c.z = c.z.zzzz;
83919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				c.w = c.w.wwww;
84019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
84119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else
84219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
84319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int component = src.rel.swizzle & 0x03;
84419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Float4 a;
84519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
84619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				switch(src.rel.type)
84719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
8487551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_ADDR:   a = a0[component]; break;
8497551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_TEMP:   a = r[src.rel.index][component]; break;
8507551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_INPUT:  a = v[src.rel.index][component]; break;
8517551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_OUTPUT: a = o[src.rel.index][component]; break;
8522c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				case Shader::PARAMETER_CONST:  a = *Pointer<Float>(uniformAddress(src.bufferIndex, src.rel.index) + component * sizeof(float)); break;
85319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				default: ASSERT(false);
85419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
85519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
85602a2bb807c1e947bc99d68ba7dd4984289278be0Alexis Hetu				Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
85719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
858028f41ba4d7b96e4281d69183ded014b69ab7c2cAlexis Hetu				index = Min(As<UInt4>(index), UInt4(VERTEX_UNIFORM_VECTORS));   // Clamp to constant register range, c[VERTEX_UNIFORM_VECTORS] = {0, 0, 0, 0}
859b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
86019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Int index0 = Extract(index, 0);
86119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Int index1 = Extract(index, 1);
86219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Int index2 = Extract(index, 2);
86319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Int index3 = Extract(index, 3);
86419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8652c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				c.x = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index0), 16);
8662c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				c.y = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index1), 16);
8672c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				c.z = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index2), 16);
8682c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu				c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index3), 16);
86919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
87019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				transpose4x4(c.x, c.y, c.z, c.w);
87119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
87219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
87319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
87419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		return c;
87519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
87619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8772c2a7b29cd53cb7b06ef1b1e2177a8c90e6e0128Alexis Hetu	Int VertexProgram::relativeAddress(const Shader::Parameter &var, int bufferIndex)
87819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
87919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		ASSERT(var.rel.deterministic);
88019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
88119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(var.rel.type == Shader::PARAMETER_TEMP)
88219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8837551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			return As<Int>(Extract(r[var.rel.index].x, 0)) * var.rel.scale;
88419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
88519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(var.rel.type == Shader::PARAMETER_INPUT)
88619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			return As<Int>(Extract(v[var.rel.index].x, 0)) * var.rel.scale;
88819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
88919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(var.rel.type == Shader::PARAMETER_OUTPUT)
89019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8917551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			return As<Int>(Extract(o[var.rel.index].x, 0)) * var.rel.scale;
89219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
89319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(var.rel.type == Shader::PARAMETER_CONST)
89419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
89548be735fa7eb1e2684a631cc4270a4503c7d235aAlexis Hetu			return *Pointer<Int>(uniformAddress(bufferIndex, var.rel.index)) * var.rel.scale;
89619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
897907700d11aff5aebfbe7d003a236500109c73d49Nicolas Capens		else if(var.rel.type == Shader::PARAMETER_LOOP)
898907700d11aff5aebfbe7d003a236500109c73d49Nicolas Capens		{
8997551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			return aL[loopDepth];
900907700d11aff5aebfbe7d003a236500109c73d49Nicolas Capens		}
90119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else ASSERT(false);
90219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
90319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		return 0;
90419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
90519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
906b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
90719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
9087551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
909b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
910d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman		if(!whileTest)
91119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
912d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			if(shader->containsBreakInstruction() && instruction->analysisBreak)
913d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			{
9147551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				enable &= enableBreak;
915d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			}
91619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
917d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			if(shader->containsContinueInstruction() && instruction->analysisContinue)
918d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			{
9197551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				enable &= enableContinue;
920d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			}
92119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
922d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			if(shader->containsLeaveInstruction() && instruction->analysisLeave)
923d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			{
9247551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				enable &= enableLeave;
925d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			}
92619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
92719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
92819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		return enable;
92919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
93019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
931b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M3X2(Vector4f &dst, Vector4f &src0, Src &src1)
93219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
933c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row0 = fetchRegister(src1, 0);
934c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row1 = fetchRegister(src1, 1);
935894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
936894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot3(src0, row0);
937894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot3(src0, row1);
938894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
939894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
940b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M3X3(Vector4f &dst, Vector4f &src0, Src &src1)
941894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
942c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row0 = fetchRegister(src1, 0);
943c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row1 = fetchRegister(src1, 1);
944c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row2 = fetchRegister(src1, 2);
945894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
946894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot3(src0, row0);
947894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot3(src0, row1);
948894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = dot3(src0, row2);
949894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
950894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
951b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M3X4(Vector4f &dst, Vector4f &src0, Src &src1)
952894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
953c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row0 = fetchRegister(src1, 0);
954c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row1 = fetchRegister(src1, 1);
955c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row2 = fetchRegister(src1, 2);
956c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row3 = fetchRegister(src1, 3);
957894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
958894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot3(src0, row0);
959894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot3(src0, row1);
960894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = dot3(src0, row2);
961894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.w = dot3(src0, row3);
962894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
963894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
964b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M4X3(Vector4f &dst, Vector4f &src0, Src &src1)
965894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
966c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row0 = fetchRegister(src1, 0);
967c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row1 = fetchRegister(src1, 1);
968c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row2 = fetchRegister(src1, 2);
969894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
970894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot4(src0, row0);
971894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot4(src0, row1);
972894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = dot4(src0, row2);
973894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
974894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
975b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M4X4(Vector4f &dst, Vector4f &src0, Src &src1)
976894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
977c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row0 = fetchRegister(src1, 0);
978c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row1 = fetchRegister(src1, 1);
979c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row2 = fetchRegister(src1, 2);
980c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f row3 = fetchRegister(src1, 3);
981894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
982894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot4(src0, row0);
983894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot4(src0, row1);
984894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = dot4(src0, row2);
985894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.w = dot4(src0, row3);
986894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
987894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
988b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::BREAK()
989894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
990894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *deadBlock = Nucleus::createBasicBlock();
991894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth - 1];
992894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
993894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(breakDepth == 0)
994894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
9957551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableIndex = enableIndex - breakDepth;
996894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::createBr(endBlock);
997894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
998894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
999894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
10007551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableBreak = enableBreak & ~enableStack[enableIndex];
10017551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Bool allBreak = SignMask(enableBreak) == 0x0;
1002894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10037551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableIndex = enableIndex - breakDepth;
1004894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			branch(allBreak, endBlock, deadBlock);
1005894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1006894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1007894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(deadBlock);
10087551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex = enableIndex + breakDepth;
1009894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1010894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1011b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
1012894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1013894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Int4 condition;
1014894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1015894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(control)
1016894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
101719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_GT: condition = CmpNLE(src0.x,  src1.x);	break;
101819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x);		break;
101919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x);	break;
102019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_LT: condition = CmpLT(src0.x,  src1.x);	break;
102119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x);	break;
102219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x);		break;
1023894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
1024894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
1025894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1026894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1027b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		BREAK(condition);
1028894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1029894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1030b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::BREAKP(const Src &predicateRegister)   // FIXME: Factor out parts common with BREAKC
1031894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
10327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
1033894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
103419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1035894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1036894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			condition = ~condition;
1037894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1038894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1039b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		BREAK(condition);
104019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
104119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1042b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::BREAK(Int4 &condition)
104319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
10447551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		condition &= enableStack[enableIndex];
1045894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1046894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *continueBlock = Nucleus::createBasicBlock();
1047894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth - 1];
1048894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10497551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = enableBreak & ~condition;
10507551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Bool allBreak = SignMask(enableBreak) == 0x0;
1051894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10527551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex = enableIndex - breakDepth;
1053894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		branch(allBreak, endBlock, continueBlock);
105419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1055894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(continueBlock);
10567551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex = enableIndex + breakDepth;
1057894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1058894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1059b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CONTINUE()
106019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
10617551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableContinue = enableContinue & ~enableStack[enableIndex];
106219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
106319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
106419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	void VertexProgram::TEST()
106519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
106619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		whileTest = true;
106719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
106819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1069b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CALL(int labelIndex, int callSiteIndex)
1070894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1071894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!labelBlock[labelIndex])
1072894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1073894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			labelBlock[labelIndex] = Nucleus::createBasicBlock();
1074894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1075894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
107619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(callRetBlock[labelIndex].size() > 1)
107719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
10787551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			callStack[stackIndex++] = UInt(callSiteIndex);
107919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1080894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10817551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreLeave = enableLeave;
1082894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1083894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(labelBlock[labelIndex]);
108419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
108519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
10867551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableLeave = restoreLeave;
1087894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1088894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1089b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CALLNZ(int labelIndex, int callSiteIndex, const Src &src)
1090894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
109119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(src.type == Shader::PARAMETER_CONSTBOOL)
1092894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1093b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			CALLNZb(labelIndex, callSiteIndex, src);
1094894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
109519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(src.type == Shader::PARAMETER_PREDICATE)
1096894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1097b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			CALLNZp(labelIndex, callSiteIndex, src);
1098894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1099894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else ASSERT(false);
1100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1102b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister)
1103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
11047551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0));   // FIXME
1105b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
110619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(boolRegister.modifier == Shader::MODIFIER_NOT)
1107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1108b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			condition = !condition;
1109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!labelBlock[labelIndex])
1112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			labelBlock[labelIndex] = Nucleus::createBasicBlock();
1114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
111619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(callRetBlock[labelIndex].size() > 1)
111719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
11187551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			callStack[stackIndex++] = UInt(callSiteIndex);
111919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11217551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreLeave = enableLeave;
1122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
112319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		branch(condition, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
112419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
112519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
11267551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableLeave = restoreLeave;
1127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1129b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister)
1130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
11317551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
1132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
113319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			condition = ~condition;
1136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11387551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		condition &= enableStack[enableIndex];
1139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!labelBlock[labelIndex])
1141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			labelBlock[labelIndex] = Nucleus::createBasicBlock();
1143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
114519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(callRetBlock[labelIndex].size() > 1)
114619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
11477551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			callStack[stackIndex++] = UInt(callSiteIndex);
114819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11507551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex++;
11517551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableStack[enableIndex] = condition;
11527551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreLeave = enableLeave;
1153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
115419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Bool notAllFalse = SignMask(condition) != 0;
115519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		branch(notAllFalse, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
115619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11587551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex--;
11597551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableLeave = restoreLeave;
1160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1162b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ELSE()
1163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth--;
1165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *falseBlock = ifFalseBlock[ifDepth];
1167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(isConditionalIf[ifDepth])
1170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
11717551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Int4 condition = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
117219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Bool notAllFalse = SignMask(condition) != 0;
1173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			branch(notAllFalse, falseBlock, endBlock);
1175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11767551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableStack[enableIndex] = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
1177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
1179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::createBr(endBlock);
1181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::setInsertBlock(falseBlock);
1182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifFalseBlock[ifDepth] = endBlock;
1185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth++;
1187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1189b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ENDIF()
1190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth--;
1192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = ifFalseBlock[ifDepth];
1194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(endBlock);
1196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(endBlock);
1197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(isConditionalIf[ifDepth])
1199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			breakDepth--;
12017551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableIndex--;
1202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1205b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ENDLOOP()
1206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth--;
1208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12097551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		aL[loopDepth] = aL[loopDepth] + increment[loopDepth];   // FIXME: +=
121019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(testBlock);
1215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(endBlock);
1216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12177551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth--;
12187551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
1219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1221b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ENDREP()
1222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth--;
1224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1225894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1227894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(testBlock);
1229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(endBlock);
1230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12317551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth--;
12327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
1233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1235b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ENDWHILE()
123619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
123719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		loopRepDepth--;
123819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
123919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
124019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
124119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
124219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::createBr(testBlock);
124319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(endBlock);
124419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
12457551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex--;
12467551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
124719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		whileTest = false;
124819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
124919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1250b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IF(const Src &src)
1251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
125219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(src.type == Shader::PARAMETER_CONSTBOOL)
1253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1254b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			IFb(src);
1255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
125619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(src.type == Shader::PARAMETER_PREDICATE)
1257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1258b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			IFp(src);
1259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
126019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else
126119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
1262c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			Int4 condition = As<Int4>(fetchRegister(src).x);
1263b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			IF(condition);
126419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1267b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IFb(const Src &boolRegister)
1268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ASSERT(ifDepth < 24 + 4);
1270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12717551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0));   // FIXME
1272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
127319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(boolRegister.modifier == Shader::MODIFIER_NOT)
1274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
127519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			condition = !condition;
1276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *trueBlock = Nucleus::createBasicBlock();
1279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *falseBlock = Nucleus::createBasicBlock();
1280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		branch(condition, trueBlock, falseBlock);
1282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		isConditionalIf[ifDepth] = false;
1284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifFalseBlock[ifDepth] = falseBlock;
1285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth++;
1287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1289b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IFp(const Src &predicateRegister)
1290894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
12917551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
1292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
129319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			condition = ~condition;
1296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1297894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1298b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		IF(condition);
1299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1301b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IFC(Vector4f &src0, Vector4f &src1, Control control)
1302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1303894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Int4 condition;
1304894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1305894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(control)
1306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
130719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_GT: condition = CmpNLE(src0.x,  src1.x);	break;
130819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x);		break;
130919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x);	break;
131019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_LT: condition = CmpLT(src0.x,  src1.x);	break;
131119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x);	break;
131219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x);		break;
1313894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
1314894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
1315894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1316894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1317b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		IF(condition);
131819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
131919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1320b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IF(Int4 &condition)
132119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
13227551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		condition &= enableStack[enableIndex];
1323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13247551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex++;
13257551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableStack[enableIndex] = condition;
1326894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1327894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *trueBlock = Nucleus::createBasicBlock();
1328894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *falseBlock = Nucleus::createBasicBlock();
1329894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
133019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Bool notAllFalse = SignMask(condition) != 0;
1331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1332894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		branch(notAllFalse, trueBlock, falseBlock);
1333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		isConditionalIf[ifDepth] = true;
1335894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifFalseBlock[ifDepth] = falseBlock;
1336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth++;
1338894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		breakDepth++;
1339894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1340894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void VertexProgram::LABEL(int labelIndex)
1342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
134319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(!labelBlock[labelIndex])
134419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
134519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			labelBlock[labelIndex] = Nucleus::createBasicBlock();
134619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
134719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(labelBlock[labelIndex]);
134919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		currentLabel = labelIndex;
1350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1352b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::LOOP(const Src &integerRegister)
1353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
13547551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth++;
1355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13567551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
13577551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		aL[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][1]));
13587551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		increment[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][2]));
1359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// FIXME: Compiles to two instructions?
13617551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		If(increment[loopDepth] == 0)
1362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
13637551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			increment[loopDepth] = 1;
1364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepTestBlock[loopRepDepth] = testBlock;
1371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepEndBlock[loopRepDepth] = endBlock;
1372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// FIXME: jump(testBlock)
1374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(testBlock);
1375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(testBlock);
1376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13777551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		branch(iteration[loopDepth] > 0, loopBlock, endBlock);
1378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(loopBlock);
1379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13807551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		iteration[loopDepth] = iteration[loopDepth] - 1;   // FIXME: --
1381b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
1382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth++;
1383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		breakDepth = 0;
1384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1386b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::REP(const Src &integerRegister)
1387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
13887551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth++;
1389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13907551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
13917551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		aL[loopDepth] = aL[loopDepth - 1];
1392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1395894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepTestBlock[loopRepDepth] = testBlock;
1398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepEndBlock[loopRepDepth] = endBlock;
1399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// FIXME: jump(testBlock)
1401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(testBlock);
1402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(testBlock);
1403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
14047551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		branch(iteration[loopDepth] > 0, loopBlock, endBlock);
1405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(loopBlock);
1406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
14077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		iteration[loopDepth] = iteration[loopDepth] - 1;   // FIXME: --
1408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth++;
1410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		breakDepth = 0;
1411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1413b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::WHILE(const Src &temporaryRegister)
141419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
14157551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex++;
141619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
141719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
141819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
141919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1420b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
142119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		loopRepTestBlock[loopRepDepth] = testBlock;
142219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		loopRepEndBlock[loopRepDepth] = endBlock;
142319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
14247551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreBreak = enableBreak;
14257551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreContinue = enableContinue;
142619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
142719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		// FIXME: jump(testBlock)
142819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::createBr(testBlock);
142919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(testBlock);
14307551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableContinue = restoreContinue;
143119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1432c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		const Vector4f &src = fetchRegister(temporaryRegister);
143319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Int4 condition = As<Int4>(src.x);
14347551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		condition &= enableStack[enableIndex - 1];
14357551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableStack[enableIndex] = condition;
143619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
143719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Bool notAllFalse = SignMask(condition) != 0;
143819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		branch(notAllFalse, loopBlock, endBlock);
1439b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
144019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(endBlock);
14417551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = restoreBreak;
1442b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
144319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(loopBlock);
144419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
144519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		loopRepDepth++;
144619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		breakDepth = 0;
144719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
144819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1449b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::RET()
1450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
145119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(currentLabel == -1)
1452894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1453894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			returnBlock = Nucleus::createBasicBlock();
1454894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::createBr(returnBlock);
1455894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1456894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
1457894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			llvm::BasicBlock *unreachableBlock = Nucleus::createBasicBlock();
1459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
146019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(callRetBlock[currentLabel].size() > 1)   // Pop the return destination from the call stack
1461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
146219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				// FIXME: Encapsulate
14637551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				UInt index = callStack[--stackIndex];
1464b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
146566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				llvm::Value *value = index.loadValue();
146619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				llvm::Value *switchInst = Nucleus::createSwitch(value, unreachableBlock, (int)callRetBlock[currentLabel].size());
146719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
146819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				for(unsigned int i = 0; i < callRetBlock[currentLabel].size(); i++)
146919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
147019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Nucleus::addSwitchCase(switchInst, i, callRetBlock[currentLabel][i]);
147119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
147219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
147319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else if(callRetBlock[currentLabel].size() == 1)   // Jump directly to the unique return destination
147419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
147519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Nucleus::createBr(callRetBlock[currentLabel][0]);
147619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
147719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else   // Function isn't called
147819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
147919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Nucleus::createBr(unreachableBlock);
1480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::setInsertBlock(unreachableBlock);
1483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::createUnreachable();
1484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1486894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1487b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::LEAVE()
1488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
14897551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableLeave = enableLeave & ~enableStack[enableIndex];
149019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
149119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		// FIXME: Return from function if all instances left
149219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		// FIXME: Use enableLeave in other control-flow constructs
149319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
1494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1495b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1)
149619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
1497c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		sampleTexture(dst, src1, src0.x, src0.y, src0.z, src0.w, Lod);
149819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
1499894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1500b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1)
150119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
1502c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Float4 lod0 = Float4(0.0f);
1503c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		sampleTexture(dst, src1, src0.x, src0.y, src0.z, lod0, Lod);
1504894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
150519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1506b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
150725d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
150825d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
150925d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
151025d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1511b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src, const Src&, Vector4f &offset)
151225d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
151325d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
151425d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
151525d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1516b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2)
151725d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
151825d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
151925d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
152025d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1521b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &offset)
152225d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
152325d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
152425d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
152525d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1526b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
152725d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
152825d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
152925d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
153025d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1531b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3, Vector4f &offset)
153225d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
153325d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
153425d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
153525d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1536b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
15379bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu	{
15387551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Pointer<Byte> textureMipmap = data + OFFSET(DrawData, mipmap[16]) + src1.index * sizeof(Texture) + OFFSET(Texture, mipmap);
15399bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu		for(int i = 0; i < 4; ++i)
15409bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu		{
15419bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu			Pointer<Byte> mipmap = textureMipmap + (As<Int>(Extract(lod, i)) + Int(1)) * sizeof(Mipmap);
15429bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu			dst.x = Insert(dst.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
15439bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu			dst.y = Insert(dst.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
15449bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu			dst.z = Insert(dst.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
15459bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu		}
15469bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu	}
15479bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu
1548c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens	void VertexProgram::sampleTexture(Vector4f &c, const Src &s, Float4 &u, Float4 &v, Float4 &w, Float4 &q, SamplerMethod method)
154919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
1550c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		Vector4f tmp;
1551c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens
155219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(s.type == Shader::PARAMETER_SAMPLER && s.rel.type == Shader::PARAMETER_VOID)
155319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
1554c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[TEXTURE_IMAGE_UNITS]) + s.index * sizeof(Texture);
1555c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			sampler[s.index]->sampleTexture(texture, tmp, u, v, w, q, a0, a0, method);
155619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
155719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else
155819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
1559c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			Int index = As<Int>(Float(fetchRegister(s).x.x));
156019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1561c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens			for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
156219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
156319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(shader->usesSampler(i))
156419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
156519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					If(index == i)
156619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
1567c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens						Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[TEXTURE_IMAGE_UNITS]) + i * sizeof(Texture);
1568c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens						sampler[i]->sampleTexture(texture, tmp, u, v, w, q, a0, a0, method);
156919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						// FIXME: When the sampler states are the same, we could use one sampler and just index the texture
157019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
157119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
157219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
157319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1574c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens
1575c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		c.x = tmp[(s.swizzle >> 0) & 0x3];
1576c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		c.y = tmp[(s.swizzle >> 2) & 0x3];
1577c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		c.z = tmp[(s.swizzle >> 4) & 0x3];
1578c2534f4bc37baf48d9910d3691352ff83e3bea49Nicolas Capens		c.w = tmp[(s.swizzle >> 6) & 0x3];
157919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
1580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1581