VertexProgram.cpp revision 7551ac6868ec1dc3965a00ff0a2003adbb2018d5
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
139b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegisterF(src0);
140b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegisterF(src1);
141b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegisterF(src2);
142b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegisterF(src3);
143b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegisterF(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;
160b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ADD:        add(d, s0, s1);                 break;
1618d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IADD:       iadd(d, s0, s1);                break;
162b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CRS:        crs(d, s0, s1);                 break;
163b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FORWARD1:   forward1(d, s0, s1, s2);        break;
164b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FORWARD2:   forward2(d, s0, s1, s2);        break;
165b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FORWARD3:   forward3(d, s0, s1, s2);        break;
166b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FORWARD4:   forward4(d, s0, s1, s2);        break;
167b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFLECT1:   reflect1(d, s0, s1);            break;
168b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFLECT2:   reflect2(d, s0, s1);            break;
169b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFLECT3:   reflect3(d, s0, s1);            break;
170b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFLECT4:   reflect4(d, s0, s1);            break;
171b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFRACT1:   refract1(d, s0, s1, s2.x);      break;
172b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFRACT2:   refract2(d, s0, s1, s2.x);      break;
173b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFRACT3:   refract3(d, s0, s1, s2.x);      break;
174b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REFRACT4:   refract4(d, s0, s1, s2.x);      break;
175b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DP1:        dp1(d, s0, s1);                 break;
176b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DP2:        dp2(d, s0, s1);                 break;
177b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DP3:        dp3(d, s0, s1);                 break;
178b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DP4:        dp4(d, s0, s1);                 break;
179c3d95f36258143af6cca041ede521995d8f890eaAlexis Hetu			case Shader::OPCODE_DET2:       det2(d, s0, s1);                break;
180c3d95f36258143af6cca041ede521995d8f890eaAlexis Hetu			case Shader::OPCODE_DET3:       det3(d, s0, s1, s2);            break;
181c3d95f36258143af6cca041ede521995d8f890eaAlexis Hetu			case Shader::OPCODE_DET4:       det4(d, s0, s1, s2, s3);        break;
182b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ATT:        att(d, s0, s1);                 break;
183b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXP2X:      exp2x(d, s0, pp);               break;
184b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXP2:       exp2(d, s0, pp);                break;
185b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXPP:       expp(d, s0, version);           break;
186b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXP:        exp(d, s0, pp);                 break;
187b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_FRC:        frc(d, s0);                     break;
18819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			case Shader::OPCODE_TRUNC:      trunc(d, s0);                   break;
18919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			case Shader::OPCODE_FLOOR:      floor(d, s0);                   break;
190af1970ce7685ea66dd02ac462d6f2723d6f6e500Alexis Hetu			case Shader::OPCODE_ROUND:      round(d, s0);                   break;
191b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ROUNDEVEN:  roundEven(d, s0);               break;
19219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			case Shader::OPCODE_CEIL:       ceil(d, s0);                    break;
193b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LIT:        lit(d, s0);                     break;
194b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOG2X:      log2x(d, s0, pp);               break;
195b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOG2:       log2(d, s0, pp);                break;
196b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOGP:       logp(d, s0, version);           break;
197b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOG:        log(d, s0, pp);                 break;
198b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LRP:        lrp(d, s0, s1, s2);             break;
199b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_STEP:       step(d, s0, s1);                break;
200b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SMOOTH:     smooth(d, s0, s1, s2);          break;
2018d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_FLOATBITSTOINT:
2028d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_FLOATBITSTOUINT:
2038d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_INTBITSTOFLOAT:
2048d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UINTBITSTOFLOAT: d = s0;                    break;
205b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M3X2:       M3X2(d, s0, src1);              break;
206b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M3X3:       M3X3(d, s0, src1);              break;
207b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M3X4:       M3X4(d, s0, src1);              break;
208b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M4X3:       M4X3(d, s0, src1);              break;
209b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_M4X4:       M4X4(d, s0, src1);              break;
210b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MAD:        mad(d, s0, s1, s2);             break;
211b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_IMAD:       imad(d, s0, s1, s2);            break;
212b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MAX:        max(d, s0, s1);                 break;
2138d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IMAX:       imax(d, s0, s1);                break;
2148d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UMAX:       umax(d, s0, s1);                break;
215b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MIN:        min(d, s0, s1);                 break;
2168d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IMIN:       imin(d, s0, s1);                break;
2178d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UMIN:       umin(d, s0, s1);                break;
218b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MOV:        mov(d, s0, integer);            break;
21902a2bb807c1e947bc99d68ba7dd4984289278be0Alexis Hetu			case Shader::OPCODE_MOVA:       mov(d, s0, true);               break;
2208d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_NEG:        neg(d, s0);                     break;
2218d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_INEG:       ineg(d, s0);                    break;
222b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_F2B:        f2b(d, s0);                     break;
223b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_B2F:        b2f(d, s0);                     break;
2248d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_F2I:        f2i(d, s0);                     break;
2258d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_I2F:        i2f(d, s0);                     break;
2268d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_F2U:        f2u(d, s0);                     break;
2278d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_U2F:        u2f(d, s0);                     break;
2288d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_I2B:        i2b(d, s0);                     break;
2298d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_B2I:        b2i(d, s0);                     break;
230b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MUL:        mul(d, s0, s1);                 break;
2318d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IMUL:       imul(d, s0, s1);                break;
232b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NRM2:       nrm2(d, s0, pp);                break;
233b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NRM3:       nrm3(d, s0, pp);                break;
234b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NRM4:       nrm4(d, s0, pp);                break;
235b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_POWX:       powx(d, s0, s1, pp);            break;
236b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_POW:        pow(d, s0, s1, pp);             break;
237b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_RCPX:       rcpx(d, s0, pp);                break;
238b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIV:        div(d, s0, s1);                 break;
2398d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IDIV:       idiv(d, s0, s1);                break;
2408d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UDIV:       udiv(d, s0, s1);                break;
241b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_MOD:        mod(d, s0, s1);                 break;
2428d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_IMOD:       imod(d, s0, s1);                break;
2438d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UMOD:       umod(d, s0, s1);                break;
2448d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_SHL:        shl(d, s0, s1);                 break;
245b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ISHR:       ishr(d, s0, s1);                break;
246b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_USHR:       ushr(d, s0, s1);                break;
247b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_RSQX:       rsqx(d, s0, pp);                break;
248b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SQRT:       sqrt(d, s0, pp);                break;
249b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_RSQ:        rsq(d, s0, pp);                 break;
250b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LEN2:       len2(d.x, s0, pp);              break;
251b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LEN3:       len3(d.x, s0, pp);              break;
252b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LEN4:       len4(d.x, s0, pp);              break;
253b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIST1:      dist1(d.x, s0, s1, pp);         break;
254b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIST2:      dist2(d.x, s0, s1, pp);         break;
255b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIST3:      dist3(d.x, s0, s1, pp);         break;
256b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_DIST4:      dist4(d.x, s0, s1, pp);         break;
257b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SGE:        step(d, s1, s0);                break;
258b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SGN:        sgn(d, s0);                     break;
259b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SINCOS:     sincos(d, s0, pp);              break;
260b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_COS:        cos(d, s0, pp);                 break;
261b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SIN:        sin(d, s0, pp);                 break;
262b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TAN:        tan(d, s0);                     break;
263b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ACOS:       acos(d, s0);                    break;
264b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ASIN:       asin(d, s0);                    break;
265b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ATAN:       atan(d, s0);                    break;
266b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ATAN2:      atan2(d, s0, s1);               break;
267b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_COSH:       cosh(d, s0, pp);                break;
268b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SINH:       sinh(d, s0, pp);                break;
269b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TANH:       tanh(d, s0, pp);                break;
270b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ACOSH:      acosh(d, s0, pp);               break;
271b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ASINH:      asinh(d, s0, pp);               break;
272b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ATANH:      atanh(d, s0, pp);               break;
273b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SLT:        slt(d, s0, s1);                 break;
274b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SUB:        sub(d, s0, s1);                 break;
2758d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_ISUB:       isub(d, s0, s1);                break;
276b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_BREAK:      BREAK();                        break;
277b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_BREAKC:     BREAKC(s0, s1, control);        break;
278b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_BREAKP:     BREAKP(src0);                   break;
279b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CONTINUE:   CONTINUE();                     break;
280b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEST:       TEST();                         break;
281b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CALL:       CALL(dst.label, dst.callSite);  break;
282b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CALLNZ:     CALLNZ(dst.label, dst.callSite, src0); break;
283b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ELSE:       ELSE();                         break;
284b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ENDIF:      ENDIF();                        break;
285b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ENDLOOP:    ENDLOOP();                      break;
286b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ENDREP:     ENDREP();                       break;
287b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ENDWHILE:   ENDWHILE();                     break;
288b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_IF:         IF(src0);                       break;
289b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_IFC:        IFC(s0, s1, control);           break;
290b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LABEL:      LABEL(dst.index);               break;
291b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LOOP:       LOOP(src1);                     break;
292b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_REP:        REP(src0);                      break;
293b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_WHILE:      WHILE(src0);                    break;
294b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_RET:        RET();                          break;
295b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_LEAVE:      LEAVE();                        break;
296b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_CMP:        cmp(d, s0, s1, control);        break;
297b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ICMP:       icmp(d, s0, s1, control);       break;
2988d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_UCMP:       ucmp(d, s0, s1, control);       break;
299b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_SELECT:     select(d, s0, s1, s2);          break;
300b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_EXTRACT:    extract(d.x, s0, s1.x);         break;
301b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_INSERT:     insert(d, s0, s1.x, s2.x);      break;
302b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ALL:        all(d.x, s0);                   break;
303b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_ANY:        any(d.x, s0);                   break;
304b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_NOT:        not(d, s0);                     break;
3058d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_OR:         or(d, s0, s1);                  break;
3068d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_XOR:        xor(d, s0, s1);                 break;
3078d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_AND:        and(d, s0, s1);                 break;
3088d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_EQ:         equal(d, s0, s1);               break;
3098d78cf77ce7c6bc4ba320fefb2cd2b74cc408b1aAlexis Hetu			case Shader::OPCODE_NE:         notEqual(d, s0, s1);            break;
310b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXLDL:     TEXLDL(d, s0, src1);            break;
311b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEX:        TEX(d, s0, src1);               break;
312b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXOFFSET:  TEXOFFSET(d, s0, src1, s2, s3); break;
313b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXLDLOFFSET: TEXLDL(d, s0, src1, s2);      break;
314b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXELFETCH: TEXELFETCH(d, s0, src1, s2);    break;
315b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCH(d, s0, src1, s2, s3); break;
316b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXGRAD:    TEXGRAD(d, s0, src1, s2, s3);   break;
317b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXGRADOFFSET: TEXGRAD(d, s0, src1, s2, s3, s4); break;
318b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_TEXSIZE:    TEXSIZE(d, s0.x, src1);         break;
319b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			case Shader::OPCODE_END:                                        break;
320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			default:
321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				ASSERT(false);
322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
32419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(dst.type != Shader::PARAMETER_VOID && dst.type != Shader::PARAMETER_LABEL && opcode != Shader::OPCODE_NOP)
325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
32619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(dst.integer)
32719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
32819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					switch(opcode)
32919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
33019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::OPCODE_DIV:
33119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.x) d.x = Trunc(d.x);
33219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.y) d.y = Trunc(d.y);
33319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.z) d.z = Trunc(d.z);
33419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.w) d.w = Trunc(d.w);
33519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						break;
33619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					default:
33719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						break;   // No truncation to integer required when arguments are integer
33819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
33919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
34019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
34119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(dst.saturate)
342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
34319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.x) d.x = Max(d.x, Float4(0.0f));
34419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.y) d.y = Max(d.y, Float4(0.0f));
34519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.z) d.z = Max(d.z, Float4(0.0f));
34619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.w) d.w = Max(d.w, Float4(0.0f));
34719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
34819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.x) d.x = Min(d.x, Float4(1.0f));
34919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.y) d.y = Min(d.y, Float4(1.0f));
35019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.z) d.z = Min(d.z, Float4(1.0f));
35119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.w) d.w = Min(d.w, Float4(1.0f));
352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
354c6e8ab13ecf20217229de8f4f19a14bbc18778f9Nicolas Capens				if(instruction->isPredicated())
355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
35619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Vector4f pDst;   // FIXME: Rename
357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
35819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					switch(dst.type)
359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
360b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens					case Shader::PARAMETER_VOID: break;
36119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::PARAMETER_TEMP:
36219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.rel.type == Shader::PARAMETER_VOID)
36319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						{
3647551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) pDst.x = r[dst.index].x;
3657551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) pDst.y = r[dst.index].y;
3667551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) pDst.z = r[dst.index].z;
3677551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) pDst.w = r[dst.index].w;
36819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						}
36919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						else
37019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						{
371b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens							Int a = relativeAddress(dst);
37219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
3737551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) pDst.x = r[dst.index + a].x;
3747551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) pDst.y = r[dst.index + a].y;
3757551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) pDst.z = r[dst.index + a].z;
3767551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) pDst.w = r[dst.index + a].w;
37719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						}
37819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						break;
3797551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					case Shader::PARAMETER_ADDR: pDst = a0; break;
38019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::PARAMETER_RASTOUT:
38119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						switch(dst.index)
382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 0:
3847551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) pDst.x = o[Pos].x;
3857551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) pDst.y = o[Pos].y;
3867551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) pDst.z = o[Pos].z;
3877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) pDst.w = o[Pos].w;
388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 1:
3907551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							pDst.x = o[Fog].x;
391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						case 2:
3937551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							pDst.x = o[Pts].y;
394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							break;
395894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						default:
396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							ASSERT(false);
397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
39919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::PARAMETER_ATTROUT:
4007551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) pDst.x = o[D0 + dst.index].x;
4017551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) pDst.y = o[D0 + dst.index].y;
4027551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) pDst.z = o[D0 + dst.index].z;
4037551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) pDst.w = o[D0 + dst.index].w;
404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
40519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					case Shader::PARAMETER_TEXCRDOUT:
40619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				//	case Shader::PARAMETER_OUTPUT:
407894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						if(version < 0x0300)
408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
4097551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) pDst.x = o[T0 + dst.index].x;
4107551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) pDst.y = o[T0 + dst.index].y;
4117551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) pDst.z = o[T0 + dst.index].z;
4127551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) pDst.w = o[T0 + dst.index].w;
413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						else
415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
41619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.rel.type == Shader::PARAMETER_VOID)   // Not relative
417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							{
4187551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.x) pDst.x = o[dst.index].x;
4197551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.y) pDst.y = o[dst.index].y;
4207551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.z) pDst.z = o[dst.index].z;
4217551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.w) pDst.w = o[dst.index].w;
422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							}
42319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							else
42419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							{
425b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens								Int a = relativeAddress(dst);
42619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
4277551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.x) pDst.x = o[dst.index + a].x;
4287551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.y) pDst.y = o[dst.index + a].y;
4297551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.z) pDst.z = o[dst.index + a].z;
4307551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens								if(dst.w) pDst.w = o[dst.index + a].w;
431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							}
432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
433894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
4347551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					case Shader::PARAMETER_LABEL:                break;
4357551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					case Shader::PARAMETER_PREDICATE: pDst = p0; break;
4367551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					case Shader::PARAMETER_INPUT:                break;
437894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					default:
438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						ASSERT(false);
439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
441b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens					Int4 enable = enableMask(instruction);
442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
443894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Int4 xEnable = enable;
444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Int4 yEnable = enable;
445894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Int4 zEnable = enable;
446894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Int4 wEnable = enable;
447894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(predicate)
449894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
45019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						unsigned char pSwizzle = instruction->predicateSwizzle;
451894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4527551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 xPredicate = p0[(pSwizzle >> 0) & 0x03];
4537551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 yPredicate = p0[(pSwizzle >> 2) & 0x03];
4547551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 zPredicate = p0[(pSwizzle >> 4) & 0x03];
4557551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Float4 wPredicate = p0[(pSwizzle >> 6) & 0x03];
456894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
45719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(!instruction->predicateNot)
458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
45919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.x) xEnable = xEnable & As<Int4>(xPredicate);
46019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.y) yEnable = yEnable & As<Int4>(yPredicate);
46119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.z) zEnable = zEnable & As<Int4>(zPredicate);
46219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.w) wEnable = wEnable & As<Int4>(wPredicate);
463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						else
465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
46619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.x) xEnable = xEnable & ~As<Int4>(xPredicate);
46719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.y) yEnable = yEnable & ~As<Int4>(yPredicate);
46819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.z) zEnable = zEnable & ~As<Int4>(zPredicate);
46919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							if(dst.w) wEnable = wEnable & ~As<Int4>(wPredicate);
470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
47319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.x) d.x = As<Float4>(As<Int4>(d.x) & xEnable);
47419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.y) d.y = As<Float4>(As<Int4>(d.y) & yEnable);
47519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.z) d.z = As<Float4>(As<Int4>(d.z) & zEnable);
47619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.w) d.w = As<Float4>(As<Int4>(d.w) & wEnable);
477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
47819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.x) d.x = As<Float4>(As<Int4>(d.x) | (As<Int4>(pDst.x) & ~xEnable));
47919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.y) d.y = As<Float4>(As<Int4>(d.y) | (As<Int4>(pDst.y) & ~yEnable));
48019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.z) d.z = As<Float4>(As<Int4>(d.z) | (As<Int4>(pDst.z) & ~zEnable));
48119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.w) d.w = As<Float4>(As<Int4>(d.w) | (As<Int4>(pDst.w) & ~wEnable));
482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
48419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				switch(dst.type)
485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
48619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_VOID:
487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
48819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_TEMP:
48919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dst.rel.type == Shader::PARAMETER_VOID)
49019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
4917551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) r[dst.index].x = d.x;
4927551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) r[dst.index].y = d.y;
4937551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) r[dst.index].z = d.z;
4947551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) r[dst.index].w = d.w;
49519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
49619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					else
49719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
498b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens						Int a = relativeAddress(dst);
49919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
5007551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) r[dst.index + a].x = d.x;
5017551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) r[dst.index + a].y = d.y;
5027551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) r[dst.index + a].z = d.z;
5037551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) r[dst.index + a].w = d.w;
50419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
505894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
50619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_ADDR:
5077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.x) a0.x = d.x;
5087551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.y) a0.y = d.y;
5097551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.z) a0.z = d.z;
5107551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.w) a0.w = d.w;
511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
51219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_RASTOUT:
51319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					switch(dst.index)
514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
515894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					case 0:
5167551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) o[Pos].x = d.x;
5177551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) o[Pos].y = d.y;
5187551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) o[Pos].z = d.z;
5197551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) o[Pos].w = d.w;
520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
521894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					case 1:
5227551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						o[Fog].x = d.x;
523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
524b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens					case 2:
5257551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						o[Pts].y = d.x;
526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
527894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					default:	ASSERT(false);
528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
530b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens				case Shader::PARAMETER_ATTROUT:
5317551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.x) o[D0 + dst.index].x = d.x;
5327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.y) o[D0 + dst.index].y = d.y;
5337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.z) o[D0 + dst.index].z = d.z;
5347551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					if(dst.w) o[D0 + dst.index].w = d.w;
535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
53619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::PARAMETER_TEXCRDOUT:
53719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			//	case Shader::PARAMETER_OUTPUT:
538894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(version < 0x0300)
539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
5407551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.x) o[T0 + dst.index].x = d.x;
5417551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.y) o[T0 + dst.index].y = d.y;
5427551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.z) o[T0 + dst.index].z = d.z;
5437551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						if(dst.w) o[T0 + dst.index].w = d.w;
544894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else
546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
54719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(dst.rel.type == Shader::PARAMETER_VOID)   // Not relative
548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
5497551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) o[dst.index].x = d.x;
5507551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) o[dst.index].y = d.y;
5517551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) o[dst.index].z = d.z;
5527551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) o[dst.index].w = d.w;
553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
55419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						else
55519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						{
556b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens							Int a = relativeAddress(dst);
55719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
5587551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.x) o[dst.index + a].x = d.x;
5597551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.y) o[dst.index + a].y = d.y;
5607551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.z) o[dst.index + a].z = d.z;
5617551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens							if(dst.w) o[dst.index + a].w = d.w;
562894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
5657551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_LABEL:             break;
5667551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_PREDICATE: p0 = d; break;
5677551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_INPUT:             break;
568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				default:
569894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					ASSERT(false);
570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
57419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(currentLabel != -1)
575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
576894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::setInsertBlock(returnBlock);
577894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
578894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
579894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
580b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::passThrough()
581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
58219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(shader)
583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
584894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < 12; i++)
585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
58619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				unsigned char usage = shader->output[i][0].usage;
587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
588894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				switch(usage)
589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				case 0xFF:
591894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					continue;
59219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_PSIZE:
5937551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].y = v[i].x;
594894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
59519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_TEXCOORD:
5967551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].x = v[i].x;
5977551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].y = v[i].y;
5987551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].z = v[i].z;
5997551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].w = v[i].w;
600894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
60119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_POSITION:
6027551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].x = v[i].x;
6037551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].y = v[i].y;
6047551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].z = v[i].z;
6057551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].w = v[i].w;
606894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
60719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_COLOR:
6087551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].x = v[i].x;
6097551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].y = v[i].y;
6107551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].z = v[i].z;
6117551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].w = v[i].w;
612894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
61319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				case Shader::USAGE_FOG:
6147551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens					o[i].x = v[i].x;
615894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
616894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				default:
617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					ASSERT(false);
618894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
620894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
622894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
6237551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pos].x = v[PositionT].x;
6247551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pos].y = v[PositionT].y;
6257551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pos].z = v[PositionT].z;
6267551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pos].w = v[PositionT].w;
627894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
628894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < 2; i++)
629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
6307551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[D0 + i].x = v[Color0 + i].x;
6317551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[D0 + i].y = v[Color0 + i].y;
6327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[D0 + i].z = v[Color0 + i].z;
6337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[D0 + i].w = v[Color0 + i].w;
634894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
635894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
636894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < 8; i++)
637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
6387551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + i].x = v[TexCoord0 + i].x;
6397551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + i].y = v[TexCoord0 + i].y;
6407551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + i].z = v[TexCoord0 + i].z;
6417551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				o[T0 + i].w = v[TexCoord0 + i].w;
642894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
643894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
6447551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			o[Pts].y = v[PointSize].x;
645894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
646894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
648b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	Vector4f VertexProgram::fetchRegisterF(const Src &src, unsigned int offset)
649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
65019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f reg;
6515d96188b9c35bf896c25755e4eb97d09dcf3bed7Nicolas Capens		unsigned int i = src.index + offset;
652894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
653894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(src.type)
654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
65519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_TEMP:
65619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(src.rel.type == Shader::PARAMETER_VOID)
65719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6587551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = r[i];
65919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
66019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else
66119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6627551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = r[i + relativeAddress(src)];
66319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
66419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			break;
66519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_CONST:
666b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			reg = readConstant(src, offset);
66719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			break;
66819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_INPUT:
66919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman            if(src.rel.type == Shader::PARAMETER_VOID)
67019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6717551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = v[i];
67219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
67319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else
67419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6757551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = v[i + relativeAddress(src)];
67619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
67719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman            break;
6787551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_VOID: return r[0];   // Dummy
67919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_FLOAT4LITERAL:
68019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			reg.x = Float4(src.value[0]);
68119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			reg.y = Float4(src.value[1]);
68219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			reg.z = Float4(src.value[2]);
68319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			reg.w = Float4(src.value[3]);
68419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			break;
6857551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_ADDR:      reg = a0; break;
6867551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_CONSTBOOL: return r[0];   // Dummy
6877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_CONSTINT:  return r[0];   // Dummy
6887551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_LOOP:      return r[0];   // Dummy
6897551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		case Shader::PARAMETER_PREDICATE: return r[0];   // Dummy
69019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_SAMPLER:
69119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(src.rel.type == Shader::PARAMETER_VOID)
69219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
69319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				reg.x = As<Float4>(Int4(i));
69419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
69519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else if(src.rel.type == Shader::PARAMETER_TEMP)
69619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
6977551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg.x = As<Float4>(Int4(i) + As<Int4>(r[src.rel.index].x));
69819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
69919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			return reg;
70019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::PARAMETER_OUTPUT:
70119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman            if(src.rel.type == Shader::PARAMETER_VOID)
70219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
7037551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = o[i];
70419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
70519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else
70619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
7077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				reg = o[i + relativeAddress(src)];
70819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
70919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			break;
710dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu		case Shader::PARAMETER_MISCTYPE:
7117551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			reg.x = As<Float>(Int(instanceID));
712dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu			return reg;
713894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
714894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
71766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		const Float4 &x = reg[(src.swizzle >> 0) & 0x3];
71866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		const Float4 &y = reg[(src.swizzle >> 2) & 0x3];
71966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		const Float4 &z = reg[(src.swizzle >> 4) & 0x3];
72066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		const Float4 &w = reg[(src.swizzle >> 6) & 0x3];
721894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
72266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		Vector4f mod;
723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
724894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(src.modifier)
725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
72619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_NONE:
72766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = x;
72866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = y;
72966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = z;
73066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = w;
731894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
73219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_NEGATE:
73366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = -x;
73466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = -y;
73566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = -z;
73666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = -w;
737894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
73819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_ABS:
73966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = Abs(x);
74066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = Abs(y);
74166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = Abs(z);
74266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = Abs(w);
743894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
74419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_ABS_NEGATE:
74566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = -Abs(x);
74666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = -Abs(y);
74766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = -Abs(z);
74866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = -Abs(w);
749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
75019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::MODIFIER_NOT:
75166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.x = As<Float4>(As<Int4>(x) ^ Int4(0xFFFFFFFF));
75266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.y = As<Float4>(As<Int4>(y) ^ Int4(0xFFFFFFFF));
75366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.z = As<Float4>(As<Int4>(z) ^ Int4(0xFFFFFFFF));
75466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			mod.w = As<Float4>(As<Int4>(w) ^ Int4(0xFFFFFFFF));
755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
756894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
758894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
759894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return mod;
761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
763b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	Vector4f VertexProgram::readConstant(const Src &src, unsigned int offset)
764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
76519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f c;
7665d96188b9c35bf896c25755e4eb97d09dcf3bed7Nicolas Capens		unsigned int i = src.index + offset;
76719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
76819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(src.rel.type == Shader::PARAMETER_VOID)   // Not relative
76919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
7707551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			c.x = c.y = c.z = c.w = *Pointer<Float4>(data + OFFSET(DrawData,vs.c[i]));
77119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
77219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.x = c.x.xxxx;
77319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.y = c.y.yyyy;
77419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.z = c.z.zzzz;
77519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.w = c.w.wwww;
77619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
777eafdb22c36f2077815eadf2a1db0fb6547bf0241Nicolas Capens			if(shader->containsDefineInstruction())   // Constant may be known at compile time
77819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
779903e025f6cd8d978f013c741431b87b04ae01fd1Alexis Hetu				for(size_t j = 0; j < shader->getLength(); j++)
78019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
78119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					const Shader::Instruction &instruction = *shader->getInstruction(j);
78219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
78319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(instruction.opcode == Shader::OPCODE_DEF)
78419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
78519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						if(instruction.dst.index == i)
78619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						{
78719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							c.x = Float4(instruction.src[0].value[0]);
78819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							c.y = Float4(instruction.src[0].value[1]);
78919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							c.z = Float4(instruction.src[0].value[2]);
79019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							c.w = Float4(instruction.src[0].value[3]);
79119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
79219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman							break;
79319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						}
79419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
79519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
79619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
79719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
79819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(src.rel.type == Shader::PARAMETER_LOOP)
79919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8007551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Int loopCounter = aL[loopDepth];
80119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8027551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			c.x = c.y = c.z = c.w = *Pointer<Float4>(data + OFFSET(DrawData,vs.c[i]) + loopCounter * 16);
80319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
80419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.x = c.x.xxxx;
80519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.y = c.y.yyyy;
80619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.z = c.z.zzzz;
80719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			c.w = c.w.wwww;
80819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
80919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else
81019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
81119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(src.rel.deterministic)
81219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
813b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens				Int a = relativeAddress(src);
814b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
8157551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				c.x = c.y = c.z = c.w = *Pointer<Float4>(data + OFFSET(DrawData,vs.c[i]) + a * 16);
81619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
81719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				c.x = c.x.xxxx;
81819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				c.y = c.y.yyyy;
81919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				c.z = c.z.zzzz;
82019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				c.w = c.w.wwww;
82119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
82219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else
82319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
82419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int component = src.rel.swizzle & 0x03;
82519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Float4 a;
82619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
82719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				switch(src.rel.type)
82819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
8297551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_ADDR:   a = a0[component]; break;
8307551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_TEMP:   a = r[src.rel.index][component]; break;
8317551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_INPUT:  a = v[src.rel.index][component]; break;
8327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_OUTPUT: a = o[src.rel.index][component]; break;
8337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				case Shader::PARAMETER_CONST:  a = *Pointer<Float>(data + OFFSET(DrawData,vs.c[src.rel.index][component])); break;
83419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				default: ASSERT(false);
83519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
83619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
83702a2bb807c1e947bc99d68ba7dd4984289278be0Alexis Hetu				Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
83819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
839028f41ba4d7b96e4281d69183ded014b69ab7c2cAlexis Hetu				index = Min(As<UInt4>(index), UInt4(VERTEX_UNIFORM_VECTORS));   // Clamp to constant register range, c[VERTEX_UNIFORM_VECTORS] = {0, 0, 0, 0}
840b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
84119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Int index0 = Extract(index, 0);
84219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Int index1 = Extract(index, 1);
84319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Int index2 = Extract(index, 2);
84419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Int index3 = Extract(index, 3);
84519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8467551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				c.x = *Pointer<Float4>(data + OFFSET(DrawData,vs.c) + index0 * 16, 16);
8477551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				c.y = *Pointer<Float4>(data + OFFSET(DrawData,vs.c) + index1 * 16, 16);
8487551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				c.z = *Pointer<Float4>(data + OFFSET(DrawData,vs.c) + index2 * 16, 16);
8497551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				c.w = *Pointer<Float4>(data + OFFSET(DrawData,vs.c) + index3 * 16, 16);
85019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
85119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				transpose4x4(c.x, c.y, c.z, c.w);
85219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
85319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
85419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
85519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		return c;
85619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
85719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
858b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	Int VertexProgram::relativeAddress(const Shader::Parameter &var)
85919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
86019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		ASSERT(var.rel.deterministic);
86119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
86219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(var.rel.type == Shader::PARAMETER_TEMP)
86319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8647551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			return As<Int>(Extract(r[var.rel.index].x, 0)) * var.rel.scale;
86519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
86619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(var.rel.type == Shader::PARAMETER_INPUT)
86719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8687551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			return As<Int>(Extract(v[var.rel.index].x, 0)) * var.rel.scale;
86919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
87019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(var.rel.type == Shader::PARAMETER_OUTPUT)
87119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8727551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			return As<Int>(Extract(o[var.rel.index].x, 0)) * var.rel.scale;
87319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
87419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(var.rel.type == Shader::PARAMETER_CONST)
87519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
8767551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			RValue<Int4> c = *Pointer<Int4>(data + OFFSET(DrawData, vs.c[var.rel.index]));
87719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
87802a2bb807c1e947bc99d68ba7dd4984289278be0Alexis Hetu			return Extract(c, 0) * var.rel.scale;
87919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
880907700d11aff5aebfbe7d003a236500109c73d49Nicolas Capens		else if(var.rel.type == Shader::PARAMETER_LOOP)
881907700d11aff5aebfbe7d003a236500109c73d49Nicolas Capens		{
8827551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			return aL[loopDepth];
883907700d11aff5aebfbe7d003a236500109c73d49Nicolas Capens		}
88419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else ASSERT(false);
88519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
88619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		return 0;
88719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
88819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
889b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
89019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
8917551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
892b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
893d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman		if(!whileTest)
89419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
895d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			if(shader->containsBreakInstruction() && instruction->analysisBreak)
896d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			{
8977551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				enable &= enableBreak;
898d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			}
89919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
900d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			if(shader->containsContinueInstruction() && instruction->analysisContinue)
901d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			{
9027551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				enable &= enableContinue;
903d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			}
90419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
905d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			if(shader->containsLeaveInstruction() && instruction->analysisLeave)
906d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			{
9077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				enable &= enableLeave;
908d4ae863d01d5f448dbbba6be4ecc161971a2324fJohn Bauman			}
90919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
91019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
91119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		return enable;
91219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
91319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
914b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M3X2(Vector4f &dst, Vector4f &src0, Src &src1)
91519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
916b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row0 = fetchRegisterF(src1, 0);
917b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row1 = fetchRegisterF(src1, 1);
918894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
919894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot3(src0, row0);
920894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot3(src0, row1);
921894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
922894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
923b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M3X3(Vector4f &dst, Vector4f &src0, Src &src1)
924894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
925b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row0 = fetchRegisterF(src1, 0);
926b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row1 = fetchRegisterF(src1, 1);
927b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row2 = fetchRegisterF(src1, 2);
928894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
929894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot3(src0, row0);
930894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot3(src0, row1);
931894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = dot3(src0, row2);
932894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
933894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
934b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M3X4(Vector4f &dst, Vector4f &src0, Src &src1)
935894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
936b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row0 = fetchRegisterF(src1, 0);
937b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row1 = fetchRegisterF(src1, 1);
938b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row2 = fetchRegisterF(src1, 2);
939b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row3 = fetchRegisterF(src1, 3);
940894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
941894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot3(src0, row0);
942894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot3(src0, row1);
943894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = dot3(src0, row2);
944894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.w = dot3(src0, row3);
945894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
946894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
947b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M4X3(Vector4f &dst, Vector4f &src0, Src &src1)
948894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
949b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row0 = fetchRegisterF(src1, 0);
950b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row1 = fetchRegisterF(src1, 1);
951b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row2 = fetchRegisterF(src1, 2);
952894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
953894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot4(src0, row0);
954894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot4(src0, row1);
955894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = dot4(src0, row2);
956894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
957894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
958b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::M4X4(Vector4f &dst, Vector4f &src0, Src &src1)
959894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
960b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row0 = fetchRegisterF(src1, 0);
961b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row1 = fetchRegisterF(src1, 1);
962b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row2 = fetchRegisterF(src1, 2);
963b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		Vector4f row3 = fetchRegisterF(src1, 3);
964894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
965894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = dot4(src0, row0);
966894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = dot4(src0, row1);
967894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = dot4(src0, row2);
968894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.w = dot4(src0, row3);
969894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
970894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
971b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::BREAK()
972894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
973894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *deadBlock = Nucleus::createBasicBlock();
974894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth - 1];
975894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
976894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(breakDepth == 0)
977894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
9787551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableIndex = enableIndex - breakDepth;
979894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::createBr(endBlock);
980894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
981894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
982894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
9837551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableBreak = enableBreak & ~enableStack[enableIndex];
9847551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Bool allBreak = SignMask(enableBreak) == 0x0;
985894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
9867551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableIndex = enableIndex - breakDepth;
987894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			branch(allBreak, endBlock, deadBlock);
988894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
989894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
990894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(deadBlock);
9917551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex = enableIndex + breakDepth;
992894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
993894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
994b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
995894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
996894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Int4 condition;
997894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
998894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(control)
999894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
100019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_GT: condition = CmpNLE(src0.x,  src1.x);	break;
100119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x);		break;
100219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x);	break;
100319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_LT: condition = CmpLT(src0.x,  src1.x);	break;
100419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x);	break;
100519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x);		break;
1006894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
1007894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
1008894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1009894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1010b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		BREAK(condition);
1011894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1012894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1013b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::BREAKP(const Src &predicateRegister)   // FIXME: Factor out parts common with BREAKC
1014894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
10157551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
1016894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
101719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1018894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1019894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			condition = ~condition;
1020894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1021894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1022b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		BREAK(condition);
102319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
102419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1025b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::BREAK(Int4 &condition)
102619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
10277551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		condition &= enableStack[enableIndex];
1028894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1029894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *continueBlock = Nucleus::createBasicBlock();
1030894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth - 1];
1031894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10327551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = enableBreak & ~condition;
10337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Bool allBreak = SignMask(enableBreak) == 0x0;
1034894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10357551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex = enableIndex - breakDepth;
1036894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		branch(allBreak, endBlock, continueBlock);
103719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1038894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(continueBlock);
10397551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex = enableIndex + breakDepth;
1040894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1041894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1042b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CONTINUE()
104319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
10447551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableContinue = enableContinue & ~enableStack[enableIndex];
104519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
104619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
104719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	void VertexProgram::TEST()
104819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
104919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		whileTest = true;
105019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
105119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1052b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CALL(int labelIndex, int callSiteIndex)
1053894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1054894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!labelBlock[labelIndex])
1055894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1056894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			labelBlock[labelIndex] = Nucleus::createBasicBlock();
1057894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1058894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
105919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(callRetBlock[labelIndex].size() > 1)
106019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
10617551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			callStack[stackIndex++] = UInt(callSiteIndex);
106219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1063894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10647551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreLeave = enableLeave;
1065894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1066894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(labelBlock[labelIndex]);
106719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
106819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
10697551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableLeave = restoreLeave;
1070894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1071894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1072b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CALLNZ(int labelIndex, int callSiteIndex, const Src &src)
1073894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
107419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(src.type == Shader::PARAMETER_CONSTBOOL)
1075894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1076b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			CALLNZb(labelIndex, callSiteIndex, src);
1077894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
107819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(src.type == Shader::PARAMETER_PREDICATE)
1079894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1080b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			CALLNZp(labelIndex, callSiteIndex, src);
1081894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1082894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else ASSERT(false);
1083894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1084894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1085b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister)
1086894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
10877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0));   // FIXME
1088b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
108919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(boolRegister.modifier == Shader::MODIFIER_NOT)
1090894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1091b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			condition = !condition;
1092894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1093894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1094894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!labelBlock[labelIndex])
1095894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1096894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			labelBlock[labelIndex] = Nucleus::createBasicBlock();
1097894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1098894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
109919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(callRetBlock[labelIndex].size() > 1)
110019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
11017551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			callStack[stackIndex++] = UInt(callSiteIndex);
110219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11047551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreLeave = enableLeave;
1105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
110619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		branch(condition, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
110719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
110819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
11097551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableLeave = restoreLeave;
1110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1112b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister)
1113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
11147551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
1115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
111619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			condition = ~condition;
1119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11217551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		condition &= enableStack[enableIndex];
1122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!labelBlock[labelIndex])
1124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			labelBlock[labelIndex] = Nucleus::createBasicBlock();
1126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
112819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(callRetBlock[labelIndex].size() > 1)
112919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
11307551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			callStack[stackIndex++] = UInt(callSiteIndex);
113119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex++;
11347551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableStack[enableIndex] = condition;
11357551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreLeave = enableLeave;
1136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
113719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Bool notAllFalse = SignMask(condition) != 0;
113819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		branch(notAllFalse, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
113919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11417551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex--;
11427551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableLeave = restoreLeave;
1143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1145b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ELSE()
1146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth--;
1148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *falseBlock = ifFalseBlock[ifDepth];
1150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(isConditionalIf[ifDepth])
1153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
11547551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Int4 condition = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
115519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Bool notAllFalse = SignMask(condition) != 0;
1156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			branch(notAllFalse, falseBlock, endBlock);
1158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11597551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableStack[enableIndex] = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
1160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
1162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::createBr(endBlock);
1164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::setInsertBlock(falseBlock);
1165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifFalseBlock[ifDepth] = endBlock;
1168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth++;
1170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1172b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ENDIF()
1173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth--;
1175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = ifFalseBlock[ifDepth];
1177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(endBlock);
1179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(endBlock);
1180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(isConditionalIf[ifDepth])
1182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			breakDepth--;
11847551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			enableIndex--;
1185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1188b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ENDLOOP()
1189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth--;
1191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11927551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		aL[loopDepth] = aL[loopDepth] + increment[loopDepth];   // FIXME: +=
119319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(testBlock);
1198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(endBlock);
1199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12007551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth--;
12017551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
1202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1204b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ENDREP()
1205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth--;
1207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(testBlock);
1212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(endBlock);
1213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12147551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth--;
12157551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
1216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1218b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::ENDWHILE()
121919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
122019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		loopRepDepth--;
122119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
122219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
122319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
122419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
122519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::createBr(testBlock);
122619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(endBlock);
122719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
12287551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex--;
12297551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
123019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		whileTest = false;
123119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
123219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1233b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IF(const Src &src)
1234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
123519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(src.type == Shader::PARAMETER_CONSTBOOL)
1236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1237b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			IFb(src);
1238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
123919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else if(src.type == Shader::PARAMETER_PREDICATE)
1240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1241b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			IFp(src);
1242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
124319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else
124419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
1245b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			Int4 condition = As<Int4>(fetchRegisterF(src).x);
1246b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			IF(condition);
124719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
1248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1250b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IFb(const Src &boolRegister)
1251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ASSERT(ifDepth < 24 + 4);
1253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
12547551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0));   // FIXME
1255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
125619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(boolRegister.modifier == Shader::MODIFIER_NOT)
1257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
125819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			condition = !condition;
1259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *trueBlock = Nucleus::createBasicBlock();
1262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *falseBlock = Nucleus::createBasicBlock();
1263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		branch(condition, trueBlock, falseBlock);
1265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		isConditionalIf[ifDepth] = false;
1267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifFalseBlock[ifDepth] = falseBlock;
1268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth++;
1270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1272b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IFp(const Src &predicateRegister)
1273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
12747551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
1275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
127619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			condition = ~condition;
1279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1281b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		IF(condition);
1282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1284b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IFC(Vector4f &src0, Vector4f &src1, Control control)
1285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Int4 condition;
1287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(control)
1289894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
129019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_GT: condition = CmpNLE(src0.x,  src1.x);	break;
129119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x);		break;
129219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x);	break;
129319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_LT: condition = CmpLT(src0.x,  src1.x);	break;
129419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x);	break;
129519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x);		break;
1296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
1297894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
1298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1300b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		IF(condition);
130119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
130219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1303b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::IF(Int4 &condition)
130419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
13057551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		condition &= enableStack[enableIndex];
1306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex++;
13087551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableStack[enableIndex] = condition;
1309894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1310894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *trueBlock = Nucleus::createBasicBlock();
1311894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *falseBlock = Nucleus::createBasicBlock();
1312894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
131319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Bool notAllFalse = SignMask(condition) != 0;
1314894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1315894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		branch(notAllFalse, trueBlock, falseBlock);
1316894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1317894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		isConditionalIf[ifDepth] = true;
1318894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifFalseBlock[ifDepth] = falseBlock;
1319894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ifDepth++;
1321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		breakDepth++;
1322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void VertexProgram::LABEL(int labelIndex)
1325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
132619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(!labelBlock[labelIndex])
132719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
132819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			labelBlock[labelIndex] = Nucleus::createBasicBlock();
132919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
133019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(labelBlock[labelIndex]);
133219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		currentLabel = labelIndex;
1333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1335b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::LOOP(const Src &integerRegister)
1336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
13377551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth++;
1338894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13397551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
13407551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		aL[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][1]));
13417551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		increment[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][2]));
1342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1343894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// FIXME: Compiles to two instructions?
13447551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		If(increment[loopDepth] == 0)
1345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
13467551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			increment[loopDepth] = 1;
1347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepTestBlock[loopRepDepth] = testBlock;
1354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepEndBlock[loopRepDepth] = endBlock;
1355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// FIXME: jump(testBlock)
1357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(testBlock);
1358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(testBlock);
1359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13607551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		branch(iteration[loopDepth] > 0, loopBlock, endBlock);
1361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(loopBlock);
1362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13637551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		iteration[loopDepth] = iteration[loopDepth] - 1;   // FIXME: --
1364b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
1365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth++;
1366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		breakDepth = 0;
1367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1369b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::REP(const Src &integerRegister)
1370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
13717551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		loopDepth++;
1372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13737551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
13747551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		aL[loopDepth] = aL[loopDepth - 1];
1375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepTestBlock[loopRepDepth] = testBlock;
1381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepEndBlock[loopRepDepth] = endBlock;
1382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// FIXME: jump(testBlock)
1384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::createBr(testBlock);
1385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(testBlock);
1386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13877551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		branch(iteration[loopDepth] > 0, loopBlock, endBlock);
1388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Nucleus::setInsertBlock(loopBlock);
1389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13907551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		iteration[loopDepth] = iteration[loopDepth] - 1;   // FIXME: --
1391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loopRepDepth++;
1393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		breakDepth = 0;
1394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1395894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1396b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::WHILE(const Src &temporaryRegister)
139719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
13987551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableIndex++;
139919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
140019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
140119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
140219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1403b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
140419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		loopRepTestBlock[loopRepDepth] = testBlock;
140519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		loopRepEndBlock[loopRepDepth] = endBlock;
140619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
14077551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreBreak = enableBreak;
14087551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Int4 restoreContinue = enableContinue;
140919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
141019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		// FIXME: jump(testBlock)
141119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::createBr(testBlock);
141219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(testBlock);
14137551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableContinue = restoreContinue;
141419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1415b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		const Vector4f &src = fetchRegisterF(temporaryRegister);
141619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Int4 condition = As<Int4>(src.x);
14177551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		condition &= enableStack[enableIndex - 1];
14187551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableStack[enableIndex] = condition;
141919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
142019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Bool notAllFalse = SignMask(condition) != 0;
142119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		branch(notAllFalse, loopBlock, endBlock);
1422b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
142319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(endBlock);
14247551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableBreak = restoreBreak;
1425b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
142619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Nucleus::setInsertBlock(loopBlock);
142719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
142819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		loopRepDepth++;
142919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		breakDepth = 0;
143019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
143119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1432b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::RET()
1433894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
143419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(currentLabel == -1)
1435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			returnBlock = Nucleus::createBasicBlock();
1437894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::createBr(returnBlock);
1438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
1440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			llvm::BasicBlock *unreachableBlock = Nucleus::createBasicBlock();
1442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
144319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(callRetBlock[currentLabel].size() > 1)   // Pop the return destination from the call stack
1444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
144519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				// FIXME: Encapsulate
14467551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens				UInt index = callStack[--stackIndex];
1447b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens
144866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				llvm::Value *value = index.loadValue();
144919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				llvm::Value *switchInst = Nucleus::createSwitch(value, unreachableBlock, (int)callRetBlock[currentLabel].size());
145019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
145119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				for(unsigned int i = 0; i < callRetBlock[currentLabel].size(); i++)
145219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
145319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					Nucleus::addSwitchCase(switchInst, i, callRetBlock[currentLabel][i]);
145419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
145519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
145619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else if(callRetBlock[currentLabel].size() == 1)   // Jump directly to the unique return destination
145719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
145819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Nucleus::createBr(callRetBlock[currentLabel][0]);
145919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
146019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else   // Function isn't called
146119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
146219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				Nucleus::createBr(unreachableBlock);
1463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::setInsertBlock(unreachableBlock);
1466894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Nucleus::createUnreachable();
1467894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1468894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1469894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1470b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::LEAVE()
1471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
14727551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		enableLeave = enableLeave & ~enableStack[enableIndex];
147319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
147419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		// FIXME: Return from function if all instances left
147519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		// FIXME: Use enableLeave in other control-flow constructs
147619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
1477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1478b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1)
147919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
148019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f tmp;
1481b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		sampleTexture(tmp, src1, src0.x, src0.y, src0.z, src0.w);
148219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
148319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		dst.x = tmp[(src1.swizzle >> 0) & 0x3];
148419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		dst.y = tmp[(src1.swizzle >> 2) & 0x3];
148519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		dst.z = tmp[(src1.swizzle >> 4) & 0x3];
148619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		dst.w = tmp[(src1.swizzle >> 6) & 0x3];
148719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
1488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1489b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1)
149019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
149119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Float4 lod = Float4(0.0f);
149219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		Vector4f tmp;
1493b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens		sampleTexture(tmp, src1, src0.x, src0.y, src0.z, lod);
1494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.x = tmp[(src1.swizzle >> 0) & 0x3];
1496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.y = tmp[(src1.swizzle >> 2) & 0x3];
1497894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.z = tmp[(src1.swizzle >> 4) & 0x3];
1498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		dst.w = tmp[(src1.swizzle >> 6) & 0x3];
1499894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
150019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1501b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
150225d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
150325d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
150425d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
150525d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1506b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src, const Src&, Vector4f &offset)
150725d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
150825d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
150925d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
151025d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1511b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2)
151225d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
151325d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
151425d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
151525d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1516b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &offset)
151725d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
151825d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
151925d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
152025d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1521b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
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, Vector4f &offset)
152725d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	{
152825d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu		UNIMPLEMENTED();
152925d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu	}
153025d47fc9eb8e8aaf864fab0d6aa7305d034d807bAlexis Hetu
1531b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
15329bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu	{
15337551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens		Pointer<Byte> textureMipmap = data + OFFSET(DrawData, mipmap[16]) + src1.index * sizeof(Texture) + OFFSET(Texture, mipmap);
15349bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu		for(int i = 0; i < 4; ++i)
15359bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu		{
15369bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu			Pointer<Byte> mipmap = textureMipmap + (As<Int>(Extract(lod, i)) + Int(1)) * sizeof(Mipmap);
15379bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu			dst.x = Insert(dst.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
15389bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu			dst.y = Insert(dst.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
15399bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu			dst.z = Insert(dst.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
15409bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu		}
15419bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu	}
15429bcb31da0cf95258949da1bb697f3981a70c476bAlexis Hetu
1543b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens	void VertexProgram::sampleTexture(Vector4f &c, const Src &s, Float4 &u, Float4 &v, Float4 &w, Float4 &q)
154419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
154519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		if(s.type == Shader::PARAMETER_SAMPLER && s.rel.type == Shader::PARAMETER_VOID)
154619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
15477551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[16]) + s.index * sizeof(Texture);
15487551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens			sampler[s.index]->sampleTexture(texture, c, u, v, w, q, a0, a0, false, false, true);
154919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
155019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		else
155119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		{
1552b4fb367887d4f257b20be509b8abd3ccb3a23a5aNicolas Capens			Int index = As<Int>(Float(fetchRegisterF(s).x.x));
155319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
155419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			for(int i = 0; i < 16; i++)
155519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
155619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(shader->usesSampler(i))
155719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				{
155819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					If(index == i)
155919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					{
15607551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[16]) + i * sizeof(Texture);
15617551ac6868ec1dc3965a00ff0a2003adbb2018d5Nicolas Capens						sampler[i]->sampleTexture(texture, c, u, v, w, q, a0, a0, false, false, true);
156219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman						// FIXME: When the sampler states are the same, we could use one sampler and just index the texture
156319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					}
156419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				}
156519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
156619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		}
156719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
1568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1569