blob: e0ecd7317f276d509a20ae170cf765218735a01a [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Baumand4ae8632014-05-06 16:18:33 -04003// Copyright(c) 2005-2013 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "VertexProgram.hpp"
13
14#include "Renderer.hpp"
15#include "VertexShader.hpp"
16#include "Vertex.hpp"
17#include "Half.hpp"
18#include "SamplerCore.hpp"
19#include "Debug.hpp"
20
John Bauman89401822014-05-06 15:04:28 -040021namespace sw
22{
Nicolas Capens7551ac62016-01-20 17:11:53 -050023 VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader)
24 : VertexRoutine(state, shader), shader(shader), r(shader->dynamicallyIndexedTemporaries)
John Bauman89401822014-05-06 15:04:28 -040025 {
John Bauman89401822014-05-06 15:04:28 -040026 ifDepth = 0;
27 loopRepDepth = 0;
28 breakDepth = 0;
John Bauman19bac1e2014-05-06 15:23:49 -040029 currentLabel = -1;
30 whileTest = false;
John Bauman89401822014-05-06 15:04:28 -040031
32 for(int i = 0; i < 2048; i++)
33 {
34 labelBlock[i] = 0;
35 }
Nicolas Capens7551ac62016-01-20 17:11:53 -050036
37 loopDepth = -1;
38 enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
39
40 if(shader && shader->containsBreakInstruction())
41 {
42 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
43 }
44
45 if(shader && shader->containsContinueInstruction())
46 {
47 enableContinue = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
48 }
49
50 if(shader->instanceIdDeclared)
51 {
52 instanceID = *Pointer<Int>(data + OFFSET(DrawData,instanceID));
53 }
John Bauman89401822014-05-06 15:04:28 -040054 }
55
56 VertexProgram::~VertexProgram()
57 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -040058 for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
John Bauman89401822014-05-06 15:04:28 -040059 {
60 delete sampler[i];
61 }
62 }
63
Nicolas Capensb4fb3672016-01-15 17:02:41 -050064 void VertexProgram::pipeline()
John Bauman89401822014-05-06 15:04:28 -040065 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -040066 for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
John Bauman89401822014-05-06 15:04:28 -040067 {
Nicolas Capens7551ac62016-01-20 17:11:53 -050068 sampler[i] = new SamplerCore(constants, state.samplerState[i]);
John Bauman89401822014-05-06 15:04:28 -040069 }
70
71 if(!state.preTransformed)
72 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -050073 program();
John Bauman89401822014-05-06 15:04:28 -040074 }
75 else
76 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -050077 passThrough();
John Bauman89401822014-05-06 15:04:28 -040078 }
79 }
80
Nicolas Capensb4fb3672016-01-15 17:02:41 -050081 void VertexProgram::program()
John Bauman89401822014-05-06 15:04:28 -040082 {
John Bauman19bac1e2014-05-06 15:23:49 -040083 // shader->print("VertexShader-%0.8X.txt", state.shaderID);
John Bauman89401822014-05-06 15:04:28 -040084
John Bauman19bac1e2014-05-06 15:23:49 -040085 unsigned short version = shader->getVersion();
John Bauman89401822014-05-06 15:04:28 -040086
Nicolas Capens7551ac62016-01-20 17:11:53 -050087 enableIndex = 0;
88 stackIndex = 0;
John Bauman19bac1e2014-05-06 15:23:49 -040089
Nicolas Capens4677a5f2014-05-06 16:42:26 -040090 if(shader->containsLeaveInstruction())
91 {
Nicolas Capens7551ac62016-01-20 17:11:53 -050092 enableLeave = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
Nicolas Capens4677a5f2014-05-06 16:42:26 -040093 }
94
John Bauman19bac1e2014-05-06 15:23:49 -040095 // Create all call site return blocks up front
Alexis Hetu903e0252014-11-25 14:25:32 -050096 for(size_t i = 0; i < shader->getLength(); i++)
John Bauman89401822014-05-06 15:04:28 -040097 {
John Bauman19bac1e2014-05-06 15:23:49 -040098 const Shader::Instruction *instruction = shader->getInstruction(i);
99 Shader::Opcode opcode = instruction->opcode;
John Bauman89401822014-05-06 15:04:28 -0400100
John Bauman19bac1e2014-05-06 15:23:49 -0400101 if(opcode == Shader::OPCODE_CALL || opcode == Shader::OPCODE_CALLNZ)
102 {
103 const Dst &dst = instruction->dst;
John Bauman89401822014-05-06 15:04:28 -0400104
John Bauman19bac1e2014-05-06 15:23:49 -0400105 ASSERT(callRetBlock[dst.label].size() == dst.callSite);
106 callRetBlock[dst.label].push_back(Nucleus::createBasicBlock());
107 }
108 }
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500109
Alexis Hetu903e0252014-11-25 14:25:32 -0500110 for(size_t i = 0; i < shader->getLength(); i++)
John Bauman19bac1e2014-05-06 15:23:49 -0400111 {
112 const Shader::Instruction *instruction = shader->getInstruction(i);
113 Shader::Opcode opcode = instruction->opcode;
114
115 if(opcode == Shader::OPCODE_DCL || opcode == Shader::OPCODE_DEF || opcode == Shader::OPCODE_DEFI || opcode == Shader::OPCODE_DEFB)
John Bauman89401822014-05-06 15:04:28 -0400116 {
117 continue;
118 }
119
John Bauman19bac1e2014-05-06 15:23:49 -0400120 Dst dst = instruction->dst;
121 Src src0 = instruction->src[0];
122 Src src1 = instruction->src[1];
123 Src src2 = instruction->src[2];
Alexis Hetuc3d95f32015-09-23 12:27:32 -0400124 Src src3 = instruction->src[3];
Alexis Hetu25d47fc2015-10-22 13:58:32 -0400125 Src src4 = instruction->src[4];
John Bauman89401822014-05-06 15:04:28 -0400126
John Bauman19bac1e2014-05-06 15:23:49 -0400127 bool predicate = instruction->predicate;
John Bauman19bac1e2014-05-06 15:23:49 -0400128 Control control = instruction->control;
129 bool integer = dst.type == Shader::PARAMETER_ADDR;
130 bool pp = dst.partialPrecision;
John Bauman89401822014-05-06 15:04:28 -0400131
John Bauman19bac1e2014-05-06 15:23:49 -0400132 Vector4f d;
133 Vector4f s0;
134 Vector4f s1;
135 Vector4f s2;
Alexis Hetuc3d95f32015-09-23 12:27:32 -0400136 Vector4f s3;
Alexis Hetu25d47fc2015-10-22 13:58:32 -0400137 Vector4f s4;
John Bauman89401822014-05-06 15:04:28 -0400138
Nicolas Capensc2534f42016-04-04 11:13:24 -0400139 if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
140 if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
141 if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
142 if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegister(src3);
143 if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegister(src4);
John Bauman89401822014-05-06 15:04:28 -0400144
145 switch(opcode)
146 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500147 case Shader::OPCODE_VS_1_0: break;
148 case Shader::OPCODE_VS_1_1: break;
149 case Shader::OPCODE_VS_2_0: break;
150 case Shader::OPCODE_VS_2_x: break;
151 case Shader::OPCODE_VS_2_sw: break;
152 case Shader::OPCODE_VS_3_0: break;
153 case Shader::OPCODE_VS_3_sw: break;
154 case Shader::OPCODE_DCL: break;
155 case Shader::OPCODE_DEF: break;
156 case Shader::OPCODE_DEFI: break;
157 case Shader::OPCODE_DEFB: break;
158 case Shader::OPCODE_NOP: break;
159 case Shader::OPCODE_ABS: abs(d, s0); break;
Alexis Hetu0f448072016-03-18 10:56:08 -0400160 case Shader::OPCODE_IABS: iabs(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500161 case Shader::OPCODE_ADD: add(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400162 case Shader::OPCODE_IADD: iadd(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500163 case Shader::OPCODE_CRS: crs(d, s0, s1); break;
164 case Shader::OPCODE_FORWARD1: forward1(d, s0, s1, s2); break;
165 case Shader::OPCODE_FORWARD2: forward2(d, s0, s1, s2); break;
166 case Shader::OPCODE_FORWARD3: forward3(d, s0, s1, s2); break;
167 case Shader::OPCODE_FORWARD4: forward4(d, s0, s1, s2); break;
168 case Shader::OPCODE_REFLECT1: reflect1(d, s0, s1); break;
169 case Shader::OPCODE_REFLECT2: reflect2(d, s0, s1); break;
170 case Shader::OPCODE_REFLECT3: reflect3(d, s0, s1); break;
171 case Shader::OPCODE_REFLECT4: reflect4(d, s0, s1); break;
172 case Shader::OPCODE_REFRACT1: refract1(d, s0, s1, s2.x); break;
173 case Shader::OPCODE_REFRACT2: refract2(d, s0, s1, s2.x); break;
174 case Shader::OPCODE_REFRACT3: refract3(d, s0, s1, s2.x); break;
175 case Shader::OPCODE_REFRACT4: refract4(d, s0, s1, s2.x); break;
176 case Shader::OPCODE_DP1: dp1(d, s0, s1); break;
177 case Shader::OPCODE_DP2: dp2(d, s0, s1); break;
178 case Shader::OPCODE_DP3: dp3(d, s0, s1); break;
179 case Shader::OPCODE_DP4: dp4(d, s0, s1); break;
Alexis Hetuc3d95f32015-09-23 12:27:32 -0400180 case Shader::OPCODE_DET2: det2(d, s0, s1); break;
181 case Shader::OPCODE_DET3: det3(d, s0, s1, s2); break;
182 case Shader::OPCODE_DET4: det4(d, s0, s1, s2, s3); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500183 case Shader::OPCODE_ATT: att(d, s0, s1); break;
184 case Shader::OPCODE_EXP2X: exp2x(d, s0, pp); break;
185 case Shader::OPCODE_EXP2: exp2(d, s0, pp); break;
186 case Shader::OPCODE_EXPP: expp(d, s0, version); break;
187 case Shader::OPCODE_EXP: exp(d, s0, pp); break;
188 case Shader::OPCODE_FRC: frc(d, s0); break;
John Bauman19bac1e2014-05-06 15:23:49 -0400189 case Shader::OPCODE_TRUNC: trunc(d, s0); break;
190 case Shader::OPCODE_FLOOR: floor(d, s0); break;
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400191 case Shader::OPCODE_ROUND: round(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500192 case Shader::OPCODE_ROUNDEVEN: roundEven(d, s0); break;
John Bauman19bac1e2014-05-06 15:23:49 -0400193 case Shader::OPCODE_CEIL: ceil(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500194 case Shader::OPCODE_LIT: lit(d, s0); break;
195 case Shader::OPCODE_LOG2X: log2x(d, s0, pp); break;
196 case Shader::OPCODE_LOG2: log2(d, s0, pp); break;
197 case Shader::OPCODE_LOGP: logp(d, s0, version); break;
198 case Shader::OPCODE_LOG: log(d, s0, pp); break;
199 case Shader::OPCODE_LRP: lrp(d, s0, s1, s2); break;
200 case Shader::OPCODE_STEP: step(d, s0, s1); break;
201 case Shader::OPCODE_SMOOTH: smooth(d, s0, s1, s2); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400202 case Shader::OPCODE_FLOATBITSTOINT:
203 case Shader::OPCODE_FLOATBITSTOUINT:
204 case Shader::OPCODE_INTBITSTOFLOAT:
205 case Shader::OPCODE_UINTBITSTOFLOAT: d = s0; break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500206 case Shader::OPCODE_M3X2: M3X2(d, s0, src1); break;
207 case Shader::OPCODE_M3X3: M3X3(d, s0, src1); break;
208 case Shader::OPCODE_M3X4: M3X4(d, s0, src1); break;
209 case Shader::OPCODE_M4X3: M4X3(d, s0, src1); break;
210 case Shader::OPCODE_M4X4: M4X4(d, s0, src1); break;
211 case Shader::OPCODE_MAD: mad(d, s0, s1, s2); break;
212 case Shader::OPCODE_IMAD: imad(d, s0, s1, s2); break;
213 case Shader::OPCODE_MAX: max(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400214 case Shader::OPCODE_IMAX: imax(d, s0, s1); break;
215 case Shader::OPCODE_UMAX: umax(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500216 case Shader::OPCODE_MIN: min(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400217 case Shader::OPCODE_IMIN: imin(d, s0, s1); break;
218 case Shader::OPCODE_UMIN: umin(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500219 case Shader::OPCODE_MOV: mov(d, s0, integer); break;
Alexis Hetu02a2bb82015-08-20 14:10:33 -0400220 case Shader::OPCODE_MOVA: mov(d, s0, true); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400221 case Shader::OPCODE_NEG: neg(d, s0); break;
222 case Shader::OPCODE_INEG: ineg(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500223 case Shader::OPCODE_F2B: f2b(d, s0); break;
224 case Shader::OPCODE_B2F: b2f(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400225 case Shader::OPCODE_F2I: f2i(d, s0); break;
226 case Shader::OPCODE_I2F: i2f(d, s0); break;
227 case Shader::OPCODE_F2U: f2u(d, s0); break;
228 case Shader::OPCODE_U2F: u2f(d, s0); break;
229 case Shader::OPCODE_I2B: i2b(d, s0); break;
230 case Shader::OPCODE_B2I: b2i(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500231 case Shader::OPCODE_MUL: mul(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400232 case Shader::OPCODE_IMUL: imul(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500233 case Shader::OPCODE_NRM2: nrm2(d, s0, pp); break;
234 case Shader::OPCODE_NRM3: nrm3(d, s0, pp); break;
235 case Shader::OPCODE_NRM4: nrm4(d, s0, pp); break;
236 case Shader::OPCODE_POWX: powx(d, s0, s1, pp); break;
237 case Shader::OPCODE_POW: pow(d, s0, s1, pp); break;
238 case Shader::OPCODE_RCPX: rcpx(d, s0, pp); break;
239 case Shader::OPCODE_DIV: div(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400240 case Shader::OPCODE_IDIV: idiv(d, s0, s1); break;
241 case Shader::OPCODE_UDIV: udiv(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500242 case Shader::OPCODE_MOD: mod(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400243 case Shader::OPCODE_IMOD: imod(d, s0, s1); break;
244 case Shader::OPCODE_UMOD: umod(d, s0, s1); break;
245 case Shader::OPCODE_SHL: shl(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500246 case Shader::OPCODE_ISHR: ishr(d, s0, s1); break;
247 case Shader::OPCODE_USHR: ushr(d, s0, s1); break;
248 case Shader::OPCODE_RSQX: rsqx(d, s0, pp); break;
249 case Shader::OPCODE_SQRT: sqrt(d, s0, pp); break;
250 case Shader::OPCODE_RSQ: rsq(d, s0, pp); break;
251 case Shader::OPCODE_LEN2: len2(d.x, s0, pp); break;
252 case Shader::OPCODE_LEN3: len3(d.x, s0, pp); break;
253 case Shader::OPCODE_LEN4: len4(d.x, s0, pp); break;
254 case Shader::OPCODE_DIST1: dist1(d.x, s0, s1, pp); break;
255 case Shader::OPCODE_DIST2: dist2(d.x, s0, s1, pp); break;
256 case Shader::OPCODE_DIST3: dist3(d.x, s0, s1, pp); break;
257 case Shader::OPCODE_DIST4: dist4(d.x, s0, s1, pp); break;
258 case Shader::OPCODE_SGE: step(d, s1, s0); break;
259 case Shader::OPCODE_SGN: sgn(d, s0); break;
Alexis Hetu0f448072016-03-18 10:56:08 -0400260 case Shader::OPCODE_ISGN: isgn(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500261 case Shader::OPCODE_SINCOS: sincos(d, s0, pp); break;
262 case Shader::OPCODE_COS: cos(d, s0, pp); break;
263 case Shader::OPCODE_SIN: sin(d, s0, pp); break;
264 case Shader::OPCODE_TAN: tan(d, s0); break;
265 case Shader::OPCODE_ACOS: acos(d, s0); break;
266 case Shader::OPCODE_ASIN: asin(d, s0); break;
267 case Shader::OPCODE_ATAN: atan(d, s0); break;
268 case Shader::OPCODE_ATAN2: atan2(d, s0, s1); break;
269 case Shader::OPCODE_COSH: cosh(d, s0, pp); break;
270 case Shader::OPCODE_SINH: sinh(d, s0, pp); break;
271 case Shader::OPCODE_TANH: tanh(d, s0, pp); break;
272 case Shader::OPCODE_ACOSH: acosh(d, s0, pp); break;
273 case Shader::OPCODE_ASINH: asinh(d, s0, pp); break;
274 case Shader::OPCODE_ATANH: atanh(d, s0, pp); break;
275 case Shader::OPCODE_SLT: slt(d, s0, s1); break;
276 case Shader::OPCODE_SUB: sub(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400277 case Shader::OPCODE_ISUB: isub(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500278 case Shader::OPCODE_BREAK: BREAK(); break;
279 case Shader::OPCODE_BREAKC: BREAKC(s0, s1, control); break;
280 case Shader::OPCODE_BREAKP: BREAKP(src0); break;
281 case Shader::OPCODE_CONTINUE: CONTINUE(); break;
282 case Shader::OPCODE_TEST: TEST(); break;
283 case Shader::OPCODE_CALL: CALL(dst.label, dst.callSite); break;
284 case Shader::OPCODE_CALLNZ: CALLNZ(dst.label, dst.callSite, src0); break;
285 case Shader::OPCODE_ELSE: ELSE(); break;
286 case Shader::OPCODE_ENDIF: ENDIF(); break;
287 case Shader::OPCODE_ENDLOOP: ENDLOOP(); break;
288 case Shader::OPCODE_ENDREP: ENDREP(); break;
289 case Shader::OPCODE_ENDWHILE: ENDWHILE(); break;
290 case Shader::OPCODE_IF: IF(src0); break;
291 case Shader::OPCODE_IFC: IFC(s0, s1, control); break;
292 case Shader::OPCODE_LABEL: LABEL(dst.index); break;
293 case Shader::OPCODE_LOOP: LOOP(src1); break;
294 case Shader::OPCODE_REP: REP(src0); break;
295 case Shader::OPCODE_WHILE: WHILE(src0); break;
296 case Shader::OPCODE_RET: RET(); break;
297 case Shader::OPCODE_LEAVE: LEAVE(); break;
298 case Shader::OPCODE_CMP: cmp(d, s0, s1, control); break;
299 case Shader::OPCODE_ICMP: icmp(d, s0, s1, control); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400300 case Shader::OPCODE_UCMP: ucmp(d, s0, s1, control); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500301 case Shader::OPCODE_SELECT: select(d, s0, s1, s2); break;
302 case Shader::OPCODE_EXTRACT: extract(d.x, s0, s1.x); break;
303 case Shader::OPCODE_INSERT: insert(d, s0, s1.x, s2.x); break;
304 case Shader::OPCODE_ALL: all(d.x, s0); break;
305 case Shader::OPCODE_ANY: any(d.x, s0); break;
306 case Shader::OPCODE_NOT: not(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400307 case Shader::OPCODE_OR: or(d, s0, s1); break;
308 case Shader::OPCODE_XOR: xor(d, s0, s1); break;
309 case Shader::OPCODE_AND: and(d, s0, s1); break;
310 case Shader::OPCODE_EQ: equal(d, s0, s1); break;
311 case Shader::OPCODE_NE: notEqual(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500312 case Shader::OPCODE_TEXLDL: TEXLDL(d, s0, src1); break;
313 case Shader::OPCODE_TEX: TEX(d, s0, src1); break;
314 case Shader::OPCODE_TEXOFFSET: TEXOFFSET(d, s0, src1, s2, s3); break;
315 case Shader::OPCODE_TEXLDLOFFSET: TEXLDL(d, s0, src1, s2); break;
316 case Shader::OPCODE_TEXELFETCH: TEXELFETCH(d, s0, src1, s2); break;
317 case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCH(d, s0, src1, s2, s3); break;
318 case Shader::OPCODE_TEXGRAD: TEXGRAD(d, s0, src1, s2, s3); break;
319 case Shader::OPCODE_TEXGRADOFFSET: TEXGRAD(d, s0, src1, s2, s3, s4); break;
320 case Shader::OPCODE_TEXSIZE: TEXSIZE(d, s0.x, src1); break;
321 case Shader::OPCODE_END: break;
John Bauman89401822014-05-06 15:04:28 -0400322 default:
323 ASSERT(false);
324 }
325
John Bauman19bac1e2014-05-06 15:23:49 -0400326 if(dst.type != Shader::PARAMETER_VOID && dst.type != Shader::PARAMETER_LABEL && opcode != Shader::OPCODE_NOP)
John Bauman89401822014-05-06 15:04:28 -0400327 {
John Bauman19bac1e2014-05-06 15:23:49 -0400328 if(dst.integer)
John Bauman89401822014-05-06 15:04:28 -0400329 {
John Bauman19bac1e2014-05-06 15:23:49 -0400330 switch(opcode)
331 {
332 case Shader::OPCODE_DIV:
333 if(dst.x) d.x = Trunc(d.x);
334 if(dst.y) d.y = Trunc(d.y);
335 if(dst.z) d.z = Trunc(d.z);
336 if(dst.w) d.w = Trunc(d.w);
337 break;
338 default:
339 break; // No truncation to integer required when arguments are integer
340 }
John Bauman89401822014-05-06 15:04:28 -0400341 }
342
John Bauman19bac1e2014-05-06 15:23:49 -0400343 if(dst.saturate)
John Bauman89401822014-05-06 15:04:28 -0400344 {
John Bauman19bac1e2014-05-06 15:23:49 -0400345 if(dst.x) d.x = Max(d.x, Float4(0.0f));
346 if(dst.y) d.y = Max(d.y, Float4(0.0f));
347 if(dst.z) d.z = Max(d.z, Float4(0.0f));
348 if(dst.w) d.w = Max(d.w, Float4(0.0f));
John Bauman89401822014-05-06 15:04:28 -0400349
John Bauman19bac1e2014-05-06 15:23:49 -0400350 if(dst.x) d.x = Min(d.x, Float4(1.0f));
351 if(dst.y) d.y = Min(d.y, Float4(1.0f));
352 if(dst.z) d.z = Min(d.z, Float4(1.0f));
353 if(dst.w) d.w = Min(d.w, Float4(1.0f));
354 }
355
Nicolas Capensc6e8ab12014-05-06 23:31:07 -0400356 if(instruction->isPredicated())
John Bauman19bac1e2014-05-06 15:23:49 -0400357 {
358 Vector4f pDst; // FIXME: Rename
359
360 switch(dst.type)
John Bauman89401822014-05-06 15:04:28 -0400361 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500362 case Shader::PARAMETER_VOID: break;
John Bauman19bac1e2014-05-06 15:23:49 -0400363 case Shader::PARAMETER_TEMP:
364 if(dst.rel.type == Shader::PARAMETER_VOID)
365 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500366 if(dst.x) pDst.x = r[dst.index].x;
367 if(dst.y) pDst.y = r[dst.index].y;
368 if(dst.z) pDst.z = r[dst.index].z;
369 if(dst.w) pDst.w = r[dst.index].w;
John Bauman19bac1e2014-05-06 15:23:49 -0400370 }
371 else
372 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500373 Int a = relativeAddress(dst);
John Bauman19bac1e2014-05-06 15:23:49 -0400374
Nicolas Capens7551ac62016-01-20 17:11:53 -0500375 if(dst.x) pDst.x = r[dst.index + a].x;
376 if(dst.y) pDst.y = r[dst.index + a].y;
377 if(dst.z) pDst.z = r[dst.index + a].z;
378 if(dst.w) pDst.w = r[dst.index + a].w;
John Bauman19bac1e2014-05-06 15:23:49 -0400379 }
380 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500381 case Shader::PARAMETER_ADDR: pDst = a0; break;
John Bauman19bac1e2014-05-06 15:23:49 -0400382 case Shader::PARAMETER_RASTOUT:
383 switch(dst.index)
John Bauman89401822014-05-06 15:04:28 -0400384 {
385 case 0:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500386 if(dst.x) pDst.x = o[Pos].x;
387 if(dst.y) pDst.y = o[Pos].y;
388 if(dst.z) pDst.z = o[Pos].z;
389 if(dst.w) pDst.w = o[Pos].w;
John Bauman89401822014-05-06 15:04:28 -0400390 break;
391 case 1:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500392 pDst.x = o[Fog].x;
John Bauman89401822014-05-06 15:04:28 -0400393 break;
394 case 2:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500395 pDst.x = o[Pts].y;
John Bauman89401822014-05-06 15:04:28 -0400396 break;
397 default:
398 ASSERT(false);
399 }
400 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400401 case Shader::PARAMETER_ATTROUT:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500402 if(dst.x) pDst.x = o[D0 + dst.index].x;
403 if(dst.y) pDst.y = o[D0 + dst.index].y;
404 if(dst.z) pDst.z = o[D0 + dst.index].z;
405 if(dst.w) pDst.w = o[D0 + dst.index].w;
John Bauman89401822014-05-06 15:04:28 -0400406 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400407 case Shader::PARAMETER_TEXCRDOUT:
408 // case Shader::PARAMETER_OUTPUT:
John Bauman89401822014-05-06 15:04:28 -0400409 if(version < 0x0300)
410 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500411 if(dst.x) pDst.x = o[T0 + dst.index].x;
412 if(dst.y) pDst.y = o[T0 + dst.index].y;
413 if(dst.z) pDst.z = o[T0 + dst.index].z;
414 if(dst.w) pDst.w = o[T0 + dst.index].w;
John Bauman89401822014-05-06 15:04:28 -0400415 }
416 else
417 {
John Bauman19bac1e2014-05-06 15:23:49 -0400418 if(dst.rel.type == Shader::PARAMETER_VOID) // Not relative
John Bauman89401822014-05-06 15:04:28 -0400419 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500420 if(dst.x) pDst.x = o[dst.index].x;
421 if(dst.y) pDst.y = o[dst.index].y;
422 if(dst.z) pDst.z = o[dst.index].z;
423 if(dst.w) pDst.w = o[dst.index].w;
John Bauman89401822014-05-06 15:04:28 -0400424 }
John Bauman19bac1e2014-05-06 15:23:49 -0400425 else
426 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500427 Int a = relativeAddress(dst);
John Bauman19bac1e2014-05-06 15:23:49 -0400428
Nicolas Capens7551ac62016-01-20 17:11:53 -0500429 if(dst.x) pDst.x = o[dst.index + a].x;
430 if(dst.y) pDst.y = o[dst.index + a].y;
431 if(dst.z) pDst.z = o[dst.index + a].z;
432 if(dst.w) pDst.w = o[dst.index + a].w;
John Bauman89401822014-05-06 15:04:28 -0400433 }
434 }
435 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500436 case Shader::PARAMETER_LABEL: break;
437 case Shader::PARAMETER_PREDICATE: pDst = p0; break;
438 case Shader::PARAMETER_INPUT: break;
John Bauman89401822014-05-06 15:04:28 -0400439 default:
440 ASSERT(false);
441 }
442
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500443 Int4 enable = enableMask(instruction);
John Bauman89401822014-05-06 15:04:28 -0400444
445 Int4 xEnable = enable;
446 Int4 yEnable = enable;
447 Int4 zEnable = enable;
448 Int4 wEnable = enable;
449
450 if(predicate)
451 {
John Bauman19bac1e2014-05-06 15:23:49 -0400452 unsigned char pSwizzle = instruction->predicateSwizzle;
John Bauman89401822014-05-06 15:04:28 -0400453
Nicolas Capens7551ac62016-01-20 17:11:53 -0500454 Float4 xPredicate = p0[(pSwizzle >> 0) & 0x03];
455 Float4 yPredicate = p0[(pSwizzle >> 2) & 0x03];
456 Float4 zPredicate = p0[(pSwizzle >> 4) & 0x03];
457 Float4 wPredicate = p0[(pSwizzle >> 6) & 0x03];
John Bauman89401822014-05-06 15:04:28 -0400458
John Bauman19bac1e2014-05-06 15:23:49 -0400459 if(!instruction->predicateNot)
John Bauman89401822014-05-06 15:04:28 -0400460 {
John Bauman19bac1e2014-05-06 15:23:49 -0400461 if(dst.x) xEnable = xEnable & As<Int4>(xPredicate);
462 if(dst.y) yEnable = yEnable & As<Int4>(yPredicate);
463 if(dst.z) zEnable = zEnable & As<Int4>(zPredicate);
464 if(dst.w) wEnable = wEnable & As<Int4>(wPredicate);
John Bauman89401822014-05-06 15:04:28 -0400465 }
466 else
467 {
John Bauman19bac1e2014-05-06 15:23:49 -0400468 if(dst.x) xEnable = xEnable & ~As<Int4>(xPredicate);
469 if(dst.y) yEnable = yEnable & ~As<Int4>(yPredicate);
470 if(dst.z) zEnable = zEnable & ~As<Int4>(zPredicate);
471 if(dst.w) wEnable = wEnable & ~As<Int4>(wPredicate);
John Bauman89401822014-05-06 15:04:28 -0400472 }
473 }
474
John Bauman19bac1e2014-05-06 15:23:49 -0400475 if(dst.x) d.x = As<Float4>(As<Int4>(d.x) & xEnable);
476 if(dst.y) d.y = As<Float4>(As<Int4>(d.y) & yEnable);
477 if(dst.z) d.z = As<Float4>(As<Int4>(d.z) & zEnable);
478 if(dst.w) d.w = As<Float4>(As<Int4>(d.w) & wEnable);
John Bauman89401822014-05-06 15:04:28 -0400479
John Bauman19bac1e2014-05-06 15:23:49 -0400480 if(dst.x) d.x = As<Float4>(As<Int4>(d.x) | (As<Int4>(pDst.x) & ~xEnable));
481 if(dst.y) d.y = As<Float4>(As<Int4>(d.y) | (As<Int4>(pDst.y) & ~yEnable));
482 if(dst.z) d.z = As<Float4>(As<Int4>(d.z) | (As<Int4>(pDst.z) & ~zEnable));
483 if(dst.w) d.w = As<Float4>(As<Int4>(d.w) | (As<Int4>(pDst.w) & ~wEnable));
John Bauman89401822014-05-06 15:04:28 -0400484 }
485
John Bauman19bac1e2014-05-06 15:23:49 -0400486 switch(dst.type)
John Bauman89401822014-05-06 15:04:28 -0400487 {
John Bauman19bac1e2014-05-06 15:23:49 -0400488 case Shader::PARAMETER_VOID:
John Bauman89401822014-05-06 15:04:28 -0400489 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400490 case Shader::PARAMETER_TEMP:
491 if(dst.rel.type == Shader::PARAMETER_VOID)
492 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500493 if(dst.x) r[dst.index].x = d.x;
494 if(dst.y) r[dst.index].y = d.y;
495 if(dst.z) r[dst.index].z = d.z;
496 if(dst.w) r[dst.index].w = d.w;
John Bauman19bac1e2014-05-06 15:23:49 -0400497 }
498 else
499 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500500 Int a = relativeAddress(dst);
John Bauman19bac1e2014-05-06 15:23:49 -0400501
Nicolas Capens7551ac62016-01-20 17:11:53 -0500502 if(dst.x) r[dst.index + a].x = d.x;
503 if(dst.y) r[dst.index + a].y = d.y;
504 if(dst.z) r[dst.index + a].z = d.z;
505 if(dst.w) r[dst.index + a].w = d.w;
John Bauman19bac1e2014-05-06 15:23:49 -0400506 }
John Bauman89401822014-05-06 15:04:28 -0400507 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400508 case Shader::PARAMETER_ADDR:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500509 if(dst.x) a0.x = d.x;
510 if(dst.y) a0.y = d.y;
511 if(dst.z) a0.z = d.z;
512 if(dst.w) a0.w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400513 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400514 case Shader::PARAMETER_RASTOUT:
515 switch(dst.index)
John Bauman89401822014-05-06 15:04:28 -0400516 {
517 case 0:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500518 if(dst.x) o[Pos].x = d.x;
519 if(dst.y) o[Pos].y = d.y;
520 if(dst.z) o[Pos].z = d.z;
521 if(dst.w) o[Pos].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400522 break;
523 case 1:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500524 o[Fog].x = d.x;
John Bauman89401822014-05-06 15:04:28 -0400525 break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500526 case 2:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500527 o[Pts].y = d.x;
John Bauman89401822014-05-06 15:04:28 -0400528 break;
529 default: ASSERT(false);
530 }
531 break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500532 case Shader::PARAMETER_ATTROUT:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500533 if(dst.x) o[D0 + dst.index].x = d.x;
534 if(dst.y) o[D0 + dst.index].y = d.y;
535 if(dst.z) o[D0 + dst.index].z = d.z;
536 if(dst.w) o[D0 + dst.index].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400537 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400538 case Shader::PARAMETER_TEXCRDOUT:
539 // case Shader::PARAMETER_OUTPUT:
John Bauman89401822014-05-06 15:04:28 -0400540 if(version < 0x0300)
541 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500542 if(dst.x) o[T0 + dst.index].x = d.x;
543 if(dst.y) o[T0 + dst.index].y = d.y;
544 if(dst.z) o[T0 + dst.index].z = d.z;
545 if(dst.w) o[T0 + dst.index].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400546 }
547 else
548 {
John Bauman19bac1e2014-05-06 15:23:49 -0400549 if(dst.rel.type == Shader::PARAMETER_VOID) // Not relative
John Bauman89401822014-05-06 15:04:28 -0400550 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500551 if(dst.x) o[dst.index].x = d.x;
552 if(dst.y) o[dst.index].y = d.y;
553 if(dst.z) o[dst.index].z = d.z;
554 if(dst.w) o[dst.index].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400555 }
John Bauman19bac1e2014-05-06 15:23:49 -0400556 else
557 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500558 Int a = relativeAddress(dst);
John Bauman19bac1e2014-05-06 15:23:49 -0400559
Nicolas Capens7551ac62016-01-20 17:11:53 -0500560 if(dst.x) o[dst.index + a].x = d.x;
561 if(dst.y) o[dst.index + a].y = d.y;
562 if(dst.z) o[dst.index + a].z = d.z;
563 if(dst.w) o[dst.index + a].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400564 }
565 }
566 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500567 case Shader::PARAMETER_LABEL: break;
568 case Shader::PARAMETER_PREDICATE: p0 = d; break;
569 case Shader::PARAMETER_INPUT: break;
John Bauman89401822014-05-06 15:04:28 -0400570 default:
571 ASSERT(false);
572 }
573 }
574 }
575
John Bauman19bac1e2014-05-06 15:23:49 -0400576 if(currentLabel != -1)
John Bauman89401822014-05-06 15:04:28 -0400577 {
578 Nucleus::setInsertBlock(returnBlock);
579 }
580 }
581
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500582 void VertexProgram::passThrough()
John Bauman89401822014-05-06 15:04:28 -0400583 {
John Bauman19bac1e2014-05-06 15:23:49 -0400584 if(shader)
John Bauman89401822014-05-06 15:04:28 -0400585 {
586 for(int i = 0; i < 12; i++)
587 {
John Bauman19bac1e2014-05-06 15:23:49 -0400588 unsigned char usage = shader->output[i][0].usage;
John Bauman89401822014-05-06 15:04:28 -0400589
590 switch(usage)
591 {
592 case 0xFF:
593 continue;
John Bauman19bac1e2014-05-06 15:23:49 -0400594 case Shader::USAGE_PSIZE:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500595 o[i].y = v[i].x;
John Bauman89401822014-05-06 15:04:28 -0400596 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400597 case Shader::USAGE_TEXCOORD:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500598 o[i].x = v[i].x;
599 o[i].y = v[i].y;
600 o[i].z = v[i].z;
601 o[i].w = v[i].w;
John Bauman89401822014-05-06 15:04:28 -0400602 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400603 case Shader::USAGE_POSITION:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500604 o[i].x = v[i].x;
605 o[i].y = v[i].y;
606 o[i].z = v[i].z;
607 o[i].w = v[i].w;
John Bauman89401822014-05-06 15:04:28 -0400608 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400609 case Shader::USAGE_COLOR:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500610 o[i].x = v[i].x;
611 o[i].y = v[i].y;
612 o[i].z = v[i].z;
613 o[i].w = v[i].w;
John Bauman89401822014-05-06 15:04:28 -0400614 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400615 case Shader::USAGE_FOG:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500616 o[i].x = v[i].x;
John Bauman89401822014-05-06 15:04:28 -0400617 break;
618 default:
619 ASSERT(false);
620 }
621 }
622 }
623 else
624 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500625 o[Pos].x = v[PositionT].x;
626 o[Pos].y = v[PositionT].y;
627 o[Pos].z = v[PositionT].z;
628 o[Pos].w = v[PositionT].w;
John Bauman89401822014-05-06 15:04:28 -0400629
630 for(int i = 0; i < 2; i++)
631 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500632 o[D0 + i].x = v[Color0 + i].x;
633 o[D0 + i].y = v[Color0 + i].y;
634 o[D0 + i].z = v[Color0 + i].z;
635 o[D0 + i].w = v[Color0 + i].w;
John Bauman89401822014-05-06 15:04:28 -0400636 }
637
638 for(int i = 0; i < 8; i++)
639 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500640 o[T0 + i].x = v[TexCoord0 + i].x;
641 o[T0 + i].y = v[TexCoord0 + i].y;
642 o[T0 + i].z = v[TexCoord0 + i].z;
643 o[T0 + i].w = v[TexCoord0 + i].w;
John Bauman89401822014-05-06 15:04:28 -0400644 }
645
Nicolas Capens7551ac62016-01-20 17:11:53 -0500646 o[Pts].y = v[PointSize].x;
John Bauman89401822014-05-06 15:04:28 -0400647 }
648 }
649
Nicolas Capensc2534f42016-04-04 11:13:24 -0400650 Vector4f VertexProgram::fetchRegister(const Src &src, unsigned int offset)
John Bauman89401822014-05-06 15:04:28 -0400651 {
John Bauman19bac1e2014-05-06 15:23:49 -0400652 Vector4f reg;
Nicolas Capens5d961882016-01-01 23:18:14 -0500653 unsigned int i = src.index + offset;
John Bauman89401822014-05-06 15:04:28 -0400654
John Bauman89401822014-05-06 15:04:28 -0400655 switch(src.type)
656 {
John Bauman19bac1e2014-05-06 15:23:49 -0400657 case Shader::PARAMETER_TEMP:
658 if(src.rel.type == Shader::PARAMETER_VOID)
659 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500660 reg = r[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400661 }
662 else
663 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400664 reg = r[i + relativeAddress(src, src.bufferIndex)];
John Bauman19bac1e2014-05-06 15:23:49 -0400665 }
666 break;
667 case Shader::PARAMETER_CONST:
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500668 reg = readConstant(src, offset);
John Bauman19bac1e2014-05-06 15:23:49 -0400669 break;
670 case Shader::PARAMETER_INPUT:
671 if(src.rel.type == Shader::PARAMETER_VOID)
672 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500673 reg = v[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400674 }
675 else
676 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400677 reg = v[i + relativeAddress(src, src.bufferIndex)];
John Bauman19bac1e2014-05-06 15:23:49 -0400678 }
679 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500680 case Shader::PARAMETER_VOID: return r[0]; // Dummy
John Bauman19bac1e2014-05-06 15:23:49 -0400681 case Shader::PARAMETER_FLOAT4LITERAL:
682 reg.x = Float4(src.value[0]);
683 reg.y = Float4(src.value[1]);
684 reg.z = Float4(src.value[2]);
685 reg.w = Float4(src.value[3]);
686 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500687 case Shader::PARAMETER_ADDR: reg = a0; break;
688 case Shader::PARAMETER_CONSTBOOL: return r[0]; // Dummy
689 case Shader::PARAMETER_CONSTINT: return r[0]; // Dummy
690 case Shader::PARAMETER_LOOP: return r[0]; // Dummy
691 case Shader::PARAMETER_PREDICATE: return r[0]; // Dummy
John Bauman19bac1e2014-05-06 15:23:49 -0400692 case Shader::PARAMETER_SAMPLER:
693 if(src.rel.type == Shader::PARAMETER_VOID)
694 {
695 reg.x = As<Float4>(Int4(i));
696 }
697 else if(src.rel.type == Shader::PARAMETER_TEMP)
698 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500699 reg.x = As<Float4>(Int4(i) + As<Int4>(r[src.rel.index].x));
John Bauman19bac1e2014-05-06 15:23:49 -0400700 }
701 return reg;
702 case Shader::PARAMETER_OUTPUT:
703 if(src.rel.type == Shader::PARAMETER_VOID)
704 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500705 reg = o[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400706 }
707 else
708 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400709 reg = o[i + relativeAddress(src, src.bufferIndex)];
John Bauman19bac1e2014-05-06 15:23:49 -0400710 }
711 break;
Alexis Hetudd8df682015-06-05 17:08:39 -0400712 case Shader::PARAMETER_MISCTYPE:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500713 reg.x = As<Float>(Int(instanceID));
Alexis Hetudd8df682015-06-05 17:08:39 -0400714 return reg;
John Bauman89401822014-05-06 15:04:28 -0400715 default:
716 ASSERT(false);
717 }
718
John Bauman66b8ab22014-05-06 15:57:45 -0400719 const Float4 &x = reg[(src.swizzle >> 0) & 0x3];
720 const Float4 &y = reg[(src.swizzle >> 2) & 0x3];
721 const Float4 &z = reg[(src.swizzle >> 4) & 0x3];
722 const Float4 &w = reg[(src.swizzle >> 6) & 0x3];
John Bauman89401822014-05-06 15:04:28 -0400723
John Bauman66b8ab22014-05-06 15:57:45 -0400724 Vector4f mod;
John Bauman89401822014-05-06 15:04:28 -0400725
726 switch(src.modifier)
727 {
John Bauman19bac1e2014-05-06 15:23:49 -0400728 case Shader::MODIFIER_NONE:
John Bauman66b8ab22014-05-06 15:57:45 -0400729 mod.x = x;
730 mod.y = y;
731 mod.z = z;
732 mod.w = w;
John Bauman89401822014-05-06 15:04:28 -0400733 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400734 case Shader::MODIFIER_NEGATE:
John Bauman66b8ab22014-05-06 15:57:45 -0400735 mod.x = -x;
736 mod.y = -y;
737 mod.z = -z;
738 mod.w = -w;
John Bauman89401822014-05-06 15:04:28 -0400739 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400740 case Shader::MODIFIER_ABS:
John Bauman66b8ab22014-05-06 15:57:45 -0400741 mod.x = Abs(x);
742 mod.y = Abs(y);
743 mod.z = Abs(z);
744 mod.w = Abs(w);
John Bauman89401822014-05-06 15:04:28 -0400745 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400746 case Shader::MODIFIER_ABS_NEGATE:
John Bauman66b8ab22014-05-06 15:57:45 -0400747 mod.x = -Abs(x);
748 mod.y = -Abs(y);
749 mod.z = -Abs(z);
750 mod.w = -Abs(w);
John Bauman89401822014-05-06 15:04:28 -0400751 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400752 case Shader::MODIFIER_NOT:
John Bauman66b8ab22014-05-06 15:57:45 -0400753 mod.x = As<Float4>(As<Int4>(x) ^ Int4(0xFFFFFFFF));
754 mod.y = As<Float4>(As<Int4>(y) ^ Int4(0xFFFFFFFF));
755 mod.z = As<Float4>(As<Int4>(z) ^ Int4(0xFFFFFFFF));
756 mod.w = As<Float4>(As<Int4>(w) ^ Int4(0xFFFFFFFF));
John Bauman89401822014-05-06 15:04:28 -0400757 break;
758 default:
759 ASSERT(false);
760 }
761
762 return mod;
763 }
764
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400765 RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index)
766 {
767 if(bufferIndex == -1)
768 {
769 return data + OFFSET(DrawData, vs.c[index]);
770 }
771 else
772 {
773 return *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.u[bufferIndex])) + index;
774 }
775 }
776
777 RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index, Int& offset)
778 {
779 return uniformAddress(bufferIndex, index) + offset * sizeof(float4);
780 }
781
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500782 Vector4f VertexProgram::readConstant(const Src &src, unsigned int offset)
John Bauman89401822014-05-06 15:04:28 -0400783 {
John Bauman19bac1e2014-05-06 15:23:49 -0400784 Vector4f c;
Nicolas Capens5d961882016-01-01 23:18:14 -0500785 unsigned int i = src.index + offset;
John Bauman19bac1e2014-05-06 15:23:49 -0400786
787 if(src.rel.type == Shader::PARAMETER_VOID) // Not relative
788 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400789 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i));
John Bauman19bac1e2014-05-06 15:23:49 -0400790
791 c.x = c.x.xxxx;
792 c.y = c.y.yyyy;
793 c.z = c.z.zzzz;
794 c.w = c.w.wwww;
795
Nicolas Capenseafdb222015-05-15 15:24:08 -0400796 if(shader->containsDefineInstruction()) // Constant may be known at compile time
John Bauman19bac1e2014-05-06 15:23:49 -0400797 {
Alexis Hetu903e0252014-11-25 14:25:32 -0500798 for(size_t j = 0; j < shader->getLength(); j++)
John Bauman19bac1e2014-05-06 15:23:49 -0400799 {
800 const Shader::Instruction &instruction = *shader->getInstruction(j);
801
802 if(instruction.opcode == Shader::OPCODE_DEF)
803 {
804 if(instruction.dst.index == i)
805 {
806 c.x = Float4(instruction.src[0].value[0]);
807 c.y = Float4(instruction.src[0].value[1]);
808 c.z = Float4(instruction.src[0].value[2]);
809 c.w = Float4(instruction.src[0].value[3]);
810
811 break;
812 }
813 }
814 }
815 }
816 }
817 else if(src.rel.type == Shader::PARAMETER_LOOP)
818 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500819 Int loopCounter = aL[loopDepth];
John Bauman19bac1e2014-05-06 15:23:49 -0400820
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400821 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, loopCounter));
John Bauman19bac1e2014-05-06 15:23:49 -0400822
823 c.x = c.x.xxxx;
824 c.y = c.y.yyyy;
825 c.z = c.z.zzzz;
826 c.w = c.w.wwww;
827 }
828 else
829 {
830 if(src.rel.deterministic)
831 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400832 Int a = relativeAddress(src, src.bufferIndex);
Nicolas Capensc2534f42016-04-04 11:13:24 -0400833
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400834 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, a));
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500835
John Bauman19bac1e2014-05-06 15:23:49 -0400836 c.x = c.x.xxxx;
837 c.y = c.y.yyyy;
838 c.z = c.z.zzzz;
839 c.w = c.w.wwww;
840 }
841 else
842 {
843 int component = src.rel.swizzle & 0x03;
844 Float4 a;
845
846 switch(src.rel.type)
847 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500848 case Shader::PARAMETER_ADDR: a = a0[component]; break;
849 case Shader::PARAMETER_TEMP: a = r[src.rel.index][component]; break;
850 case Shader::PARAMETER_INPUT: a = v[src.rel.index][component]; break;
851 case Shader::PARAMETER_OUTPUT: a = o[src.rel.index][component]; break;
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400852 case Shader::PARAMETER_CONST: a = *Pointer<Float>(uniformAddress(src.bufferIndex, src.rel.index) + component * sizeof(float)); break;
John Bauman19bac1e2014-05-06 15:23:49 -0400853 default: ASSERT(false);
854 }
855
Alexis Hetu02a2bb82015-08-20 14:10:33 -0400856 Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
John Bauman19bac1e2014-05-06 15:23:49 -0400857
Alexis Hetu028f41b2016-01-13 14:40:47 -0500858 index = Min(As<UInt4>(index), UInt4(VERTEX_UNIFORM_VECTORS)); // Clamp to constant register range, c[VERTEX_UNIFORM_VECTORS] = {0, 0, 0, 0}
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500859
John Bauman19bac1e2014-05-06 15:23:49 -0400860 Int index0 = Extract(index, 0);
861 Int index1 = Extract(index, 1);
862 Int index2 = Extract(index, 2);
863 Int index3 = Extract(index, 3);
864
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400865 c.x = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index0), 16);
866 c.y = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index1), 16);
867 c.z = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index2), 16);
868 c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index3), 16);
John Bauman19bac1e2014-05-06 15:23:49 -0400869
870 transpose4x4(c.x, c.y, c.z, c.w);
871 }
872 }
873
874 return c;
875 }
876
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400877 Int VertexProgram::relativeAddress(const Shader::Parameter &var, int bufferIndex)
John Bauman19bac1e2014-05-06 15:23:49 -0400878 {
879 ASSERT(var.rel.deterministic);
880
881 if(var.rel.type == Shader::PARAMETER_TEMP)
882 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500883 return As<Int>(Extract(r[var.rel.index].x, 0)) * var.rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400884 }
885 else if(var.rel.type == Shader::PARAMETER_INPUT)
886 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500887 return As<Int>(Extract(v[var.rel.index].x, 0)) * var.rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400888 }
889 else if(var.rel.type == Shader::PARAMETER_OUTPUT)
890 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500891 return As<Int>(Extract(o[var.rel.index].x, 0)) * var.rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400892 }
893 else if(var.rel.type == Shader::PARAMETER_CONST)
894 {
Alexis Hetu48be7352016-02-10 14:32:34 -0500895 return *Pointer<Int>(uniformAddress(bufferIndex, var.rel.index)) * var.rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400896 }
Nicolas Capens907700d2016-01-20 17:09:28 -0500897 else if(var.rel.type == Shader::PARAMETER_LOOP)
898 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500899 return aL[loopDepth];
Nicolas Capens907700d2016-01-20 17:09:28 -0500900 }
John Bauman19bac1e2014-05-06 15:23:49 -0400901 else ASSERT(false);
902
903 return 0;
904 }
905
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500906 Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
John Bauman19bac1e2014-05-06 15:23:49 -0400907 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500908 Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500909
John Baumand4ae8632014-05-06 16:18:33 -0400910 if(!whileTest)
John Bauman19bac1e2014-05-06 15:23:49 -0400911 {
John Baumand4ae8632014-05-06 16:18:33 -0400912 if(shader->containsBreakInstruction() && instruction->analysisBreak)
913 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500914 enable &= enableBreak;
John Baumand4ae8632014-05-06 16:18:33 -0400915 }
John Bauman19bac1e2014-05-06 15:23:49 -0400916
John Baumand4ae8632014-05-06 16:18:33 -0400917 if(shader->containsContinueInstruction() && instruction->analysisContinue)
918 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500919 enable &= enableContinue;
John Baumand4ae8632014-05-06 16:18:33 -0400920 }
John Bauman19bac1e2014-05-06 15:23:49 -0400921
John Baumand4ae8632014-05-06 16:18:33 -0400922 if(shader->containsLeaveInstruction() && instruction->analysisLeave)
923 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500924 enable &= enableLeave;
John Baumand4ae8632014-05-06 16:18:33 -0400925 }
John Bauman19bac1e2014-05-06 15:23:49 -0400926 }
927
928 return enable;
929 }
930
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500931 void VertexProgram::M3X2(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman19bac1e2014-05-06 15:23:49 -0400932 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400933 Vector4f row0 = fetchRegister(src1, 0);
934 Vector4f row1 = fetchRegister(src1, 1);
John Bauman89401822014-05-06 15:04:28 -0400935
936 dst.x = dot3(src0, row0);
937 dst.y = dot3(src0, row1);
938 }
939
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500940 void VertexProgram::M3X3(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -0400941 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400942 Vector4f row0 = fetchRegister(src1, 0);
943 Vector4f row1 = fetchRegister(src1, 1);
944 Vector4f row2 = fetchRegister(src1, 2);
John Bauman89401822014-05-06 15:04:28 -0400945
946 dst.x = dot3(src0, row0);
947 dst.y = dot3(src0, row1);
948 dst.z = dot3(src0, row2);
949 }
950
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500951 void VertexProgram::M3X4(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -0400952 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400953 Vector4f row0 = fetchRegister(src1, 0);
954 Vector4f row1 = fetchRegister(src1, 1);
955 Vector4f row2 = fetchRegister(src1, 2);
956 Vector4f row3 = fetchRegister(src1, 3);
John Bauman89401822014-05-06 15:04:28 -0400957
958 dst.x = dot3(src0, row0);
959 dst.y = dot3(src0, row1);
960 dst.z = dot3(src0, row2);
961 dst.w = dot3(src0, row3);
962 }
963
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500964 void VertexProgram::M4X3(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -0400965 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400966 Vector4f row0 = fetchRegister(src1, 0);
967 Vector4f row1 = fetchRegister(src1, 1);
968 Vector4f row2 = fetchRegister(src1, 2);
John Bauman89401822014-05-06 15:04:28 -0400969
970 dst.x = dot4(src0, row0);
971 dst.y = dot4(src0, row1);
972 dst.z = dot4(src0, row2);
973 }
974
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500975 void VertexProgram::M4X4(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -0400976 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400977 Vector4f row0 = fetchRegister(src1, 0);
978 Vector4f row1 = fetchRegister(src1, 1);
979 Vector4f row2 = fetchRegister(src1, 2);
980 Vector4f row3 = fetchRegister(src1, 3);
John Bauman89401822014-05-06 15:04:28 -0400981
982 dst.x = dot4(src0, row0);
983 dst.y = dot4(src0, row1);
984 dst.z = dot4(src0, row2);
985 dst.w = dot4(src0, row3);
986 }
987
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500988 void VertexProgram::BREAK()
John Bauman89401822014-05-06 15:04:28 -0400989 {
990 llvm::BasicBlock *deadBlock = Nucleus::createBasicBlock();
991 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth - 1];
992
993 if(breakDepth == 0)
994 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500995 enableIndex = enableIndex - breakDepth;
John Bauman89401822014-05-06 15:04:28 -0400996 Nucleus::createBr(endBlock);
997 }
998 else
999 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001000 enableBreak = enableBreak & ~enableStack[enableIndex];
1001 Bool allBreak = SignMask(enableBreak) == 0x0;
John Bauman89401822014-05-06 15:04:28 -04001002
Nicolas Capens7551ac62016-01-20 17:11:53 -05001003 enableIndex = enableIndex - breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001004 branch(allBreak, endBlock, deadBlock);
1005 }
1006
1007 Nucleus::setInsertBlock(deadBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001008 enableIndex = enableIndex + breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001009 }
1010
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001011 void VertexProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
John Bauman89401822014-05-06 15:04:28 -04001012 {
1013 Int4 condition;
1014
1015 switch(control)
1016 {
John Bauman19bac1e2014-05-06 15:23:49 -04001017 case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
1018 case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x); break;
1019 case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
1020 case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x); break;
1021 case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
1022 case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x); break;
John Bauman89401822014-05-06 15:04:28 -04001023 default:
1024 ASSERT(false);
1025 }
1026
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001027 BREAK(condition);
John Bauman89401822014-05-06 15:04:28 -04001028 }
1029
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001030 void VertexProgram::BREAKP(const Src &predicateRegister) // FIXME: Factor out parts common with BREAKC
John Bauman89401822014-05-06 15:04:28 -04001031 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001032 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001033
John Bauman19bac1e2014-05-06 15:23:49 -04001034 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001035 {
1036 condition = ~condition;
1037 }
1038
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001039 BREAK(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001040 }
1041
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001042 void VertexProgram::BREAK(Int4 &condition)
John Bauman19bac1e2014-05-06 15:23:49 -04001043 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001044 condition &= enableStack[enableIndex];
John Bauman89401822014-05-06 15:04:28 -04001045
1046 llvm::BasicBlock *continueBlock = Nucleus::createBasicBlock();
1047 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth - 1];
1048
Nicolas Capens7551ac62016-01-20 17:11:53 -05001049 enableBreak = enableBreak & ~condition;
1050 Bool allBreak = SignMask(enableBreak) == 0x0;
John Bauman89401822014-05-06 15:04:28 -04001051
Nicolas Capens7551ac62016-01-20 17:11:53 -05001052 enableIndex = enableIndex - breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001053 branch(allBreak, endBlock, continueBlock);
John Bauman19bac1e2014-05-06 15:23:49 -04001054
John Bauman89401822014-05-06 15:04:28 -04001055 Nucleus::setInsertBlock(continueBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001056 enableIndex = enableIndex + breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001057 }
1058
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001059 void VertexProgram::CONTINUE()
John Bauman19bac1e2014-05-06 15:23:49 -04001060 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001061 enableContinue = enableContinue & ~enableStack[enableIndex];
John Bauman19bac1e2014-05-06 15:23:49 -04001062 }
1063
1064 void VertexProgram::TEST()
1065 {
1066 whileTest = true;
1067 }
1068
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001069 void VertexProgram::CALL(int labelIndex, int callSiteIndex)
John Bauman89401822014-05-06 15:04:28 -04001070 {
1071 if(!labelBlock[labelIndex])
1072 {
1073 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1074 }
1075
John Bauman19bac1e2014-05-06 15:23:49 -04001076 if(callRetBlock[labelIndex].size() > 1)
1077 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001078 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001079 }
John Bauman89401822014-05-06 15:04:28 -04001080
Nicolas Capens7551ac62016-01-20 17:11:53 -05001081 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001082
1083 Nucleus::createBr(labelBlock[labelIndex]);
John Bauman19bac1e2014-05-06 15:23:49 -04001084 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1085
Nicolas Capens7551ac62016-01-20 17:11:53 -05001086 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001087 }
1088
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001089 void VertexProgram::CALLNZ(int labelIndex, int callSiteIndex, const Src &src)
John Bauman89401822014-05-06 15:04:28 -04001090 {
John Bauman19bac1e2014-05-06 15:23:49 -04001091 if(src.type == Shader::PARAMETER_CONSTBOOL)
John Bauman89401822014-05-06 15:04:28 -04001092 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001093 CALLNZb(labelIndex, callSiteIndex, src);
John Bauman89401822014-05-06 15:04:28 -04001094 }
John Bauman19bac1e2014-05-06 15:23:49 -04001095 else if(src.type == Shader::PARAMETER_PREDICATE)
John Bauman89401822014-05-06 15:04:28 -04001096 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001097 CALLNZp(labelIndex, callSiteIndex, src);
John Bauman89401822014-05-06 15:04:28 -04001098 }
1099 else ASSERT(false);
1100 }
1101
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001102 void VertexProgram::CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister)
John Bauman89401822014-05-06 15:04:28 -04001103 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001104 Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0)); // FIXME
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001105
John Bauman19bac1e2014-05-06 15:23:49 -04001106 if(boolRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001107 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001108 condition = !condition;
John Bauman89401822014-05-06 15:04:28 -04001109 }
1110
1111 if(!labelBlock[labelIndex])
1112 {
1113 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1114 }
1115
John Bauman19bac1e2014-05-06 15:23:49 -04001116 if(callRetBlock[labelIndex].size() > 1)
1117 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001118 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001119 }
John Bauman89401822014-05-06 15:04:28 -04001120
Nicolas Capens7551ac62016-01-20 17:11:53 -05001121 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001122
John Bauman19bac1e2014-05-06 15:23:49 -04001123 branch(condition, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
1124 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1125
Nicolas Capens7551ac62016-01-20 17:11:53 -05001126 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001127 }
1128
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001129 void VertexProgram::CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister)
John Bauman89401822014-05-06 15:04:28 -04001130 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001131 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001132
John Bauman19bac1e2014-05-06 15:23:49 -04001133 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001134 {
1135 condition = ~condition;
1136 }
1137
Nicolas Capens7551ac62016-01-20 17:11:53 -05001138 condition &= enableStack[enableIndex];
John Bauman89401822014-05-06 15:04:28 -04001139
1140 if(!labelBlock[labelIndex])
1141 {
1142 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1143 }
1144
John Bauman19bac1e2014-05-06 15:23:49 -04001145 if(callRetBlock[labelIndex].size() > 1)
1146 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001147 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001148 }
John Bauman89401822014-05-06 15:04:28 -04001149
Nicolas Capens7551ac62016-01-20 17:11:53 -05001150 enableIndex++;
1151 enableStack[enableIndex] = condition;
1152 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001153
John Bauman19bac1e2014-05-06 15:23:49 -04001154 Bool notAllFalse = SignMask(condition) != 0;
1155 branch(notAllFalse, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
1156 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
John Bauman89401822014-05-06 15:04:28 -04001157
Nicolas Capens7551ac62016-01-20 17:11:53 -05001158 enableIndex--;
1159 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001160 }
1161
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001162 void VertexProgram::ELSE()
John Bauman89401822014-05-06 15:04:28 -04001163 {
1164 ifDepth--;
1165
1166 llvm::BasicBlock *falseBlock = ifFalseBlock[ifDepth];
1167 llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1168
1169 if(isConditionalIf[ifDepth])
1170 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001171 Int4 condition = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
John Bauman19bac1e2014-05-06 15:23:49 -04001172 Bool notAllFalse = SignMask(condition) != 0;
John Bauman89401822014-05-06 15:04:28 -04001173
1174 branch(notAllFalse, falseBlock, endBlock);
1175
Nicolas Capens7551ac62016-01-20 17:11:53 -05001176 enableStack[enableIndex] = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
John Bauman89401822014-05-06 15:04:28 -04001177 }
1178 else
1179 {
1180 Nucleus::createBr(endBlock);
1181 Nucleus::setInsertBlock(falseBlock);
1182 }
1183
1184 ifFalseBlock[ifDepth] = endBlock;
1185
1186 ifDepth++;
1187 }
1188
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001189 void VertexProgram::ENDIF()
John Bauman89401822014-05-06 15:04:28 -04001190 {
1191 ifDepth--;
1192
1193 llvm::BasicBlock *endBlock = ifFalseBlock[ifDepth];
1194
1195 Nucleus::createBr(endBlock);
1196 Nucleus::setInsertBlock(endBlock);
1197
1198 if(isConditionalIf[ifDepth])
1199 {
1200 breakDepth--;
Nicolas Capens7551ac62016-01-20 17:11:53 -05001201 enableIndex--;
John Bauman89401822014-05-06 15:04:28 -04001202 }
1203 }
1204
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001205 void VertexProgram::ENDLOOP()
John Bauman89401822014-05-06 15:04:28 -04001206 {
1207 loopRepDepth--;
1208
Nicolas Capens7551ac62016-01-20 17:11:53 -05001209 aL[loopDepth] = aL[loopDepth] + increment[loopDepth]; // FIXME: +=
John Bauman89401822014-05-06 15:04:28 -04001210
1211 llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1212 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1213
1214 Nucleus::createBr(testBlock);
1215 Nucleus::setInsertBlock(endBlock);
1216
Nicolas Capens7551ac62016-01-20 17:11:53 -05001217 loopDepth--;
1218 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
John Bauman89401822014-05-06 15:04:28 -04001219 }
1220
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001221 void VertexProgram::ENDREP()
John Bauman19bac1e2014-05-06 15:23:49 -04001222 {
1223 loopRepDepth--;
1224
1225 llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1226 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1227
1228 Nucleus::createBr(testBlock);
1229 Nucleus::setInsertBlock(endBlock);
1230
Nicolas Capens7551ac62016-01-20 17:11:53 -05001231 loopDepth--;
1232 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
John Bauman19bac1e2014-05-06 15:23:49 -04001233 }
1234
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001235 void VertexProgram::ENDWHILE()
John Bauman19bac1e2014-05-06 15:23:49 -04001236 {
1237 loopRepDepth--;
1238
1239 llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1240 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1241
1242 Nucleus::createBr(testBlock);
1243 Nucleus::setInsertBlock(endBlock);
1244
Nicolas Capens7551ac62016-01-20 17:11:53 -05001245 enableIndex--;
1246 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
John Bauman19bac1e2014-05-06 15:23:49 -04001247 whileTest = false;
1248 }
1249
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001250 void VertexProgram::IF(const Src &src)
John Bauman89401822014-05-06 15:04:28 -04001251 {
John Bauman19bac1e2014-05-06 15:23:49 -04001252 if(src.type == Shader::PARAMETER_CONSTBOOL)
John Bauman89401822014-05-06 15:04:28 -04001253 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001254 IFb(src);
John Bauman89401822014-05-06 15:04:28 -04001255 }
John Bauman19bac1e2014-05-06 15:23:49 -04001256 else if(src.type == Shader::PARAMETER_PREDICATE)
John Bauman89401822014-05-06 15:04:28 -04001257 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001258 IFp(src);
John Bauman89401822014-05-06 15:04:28 -04001259 }
John Bauman19bac1e2014-05-06 15:23:49 -04001260 else
1261 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001262 Int4 condition = As<Int4>(fetchRegister(src).x);
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001263 IF(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001264 }
John Bauman89401822014-05-06 15:04:28 -04001265 }
1266
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001267 void VertexProgram::IFb(const Src &boolRegister)
John Bauman89401822014-05-06 15:04:28 -04001268 {
1269 ASSERT(ifDepth < 24 + 4);
1270
Nicolas Capens7551ac62016-01-20 17:11:53 -05001271 Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0)); // FIXME
John Bauman89401822014-05-06 15:04:28 -04001272
John Bauman19bac1e2014-05-06 15:23:49 -04001273 if(boolRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001274 {
John Bauman19bac1e2014-05-06 15:23:49 -04001275 condition = !condition;
John Bauman89401822014-05-06 15:04:28 -04001276 }
1277
1278 llvm::BasicBlock *trueBlock = Nucleus::createBasicBlock();
1279 llvm::BasicBlock *falseBlock = Nucleus::createBasicBlock();
1280
1281 branch(condition, trueBlock, falseBlock);
1282
1283 isConditionalIf[ifDepth] = false;
1284 ifFalseBlock[ifDepth] = falseBlock;
1285
1286 ifDepth++;
1287 }
1288
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001289 void VertexProgram::IFp(const Src &predicateRegister)
John Bauman89401822014-05-06 15:04:28 -04001290 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001291 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001292
John Bauman19bac1e2014-05-06 15:23:49 -04001293 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001294 {
1295 condition = ~condition;
1296 }
1297
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001298 IF(condition);
John Bauman89401822014-05-06 15:04:28 -04001299 }
1300
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001301 void VertexProgram::IFC(Vector4f &src0, Vector4f &src1, Control control)
John Bauman89401822014-05-06 15:04:28 -04001302 {
1303 Int4 condition;
1304
1305 switch(control)
1306 {
John Bauman19bac1e2014-05-06 15:23:49 -04001307 case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
1308 case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x); break;
1309 case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
1310 case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x); break;
1311 case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
1312 case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x); break;
John Bauman89401822014-05-06 15:04:28 -04001313 default:
1314 ASSERT(false);
1315 }
1316
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001317 IF(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001318 }
1319
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001320 void VertexProgram::IF(Int4 &condition)
John Bauman19bac1e2014-05-06 15:23:49 -04001321 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001322 condition &= enableStack[enableIndex];
John Bauman89401822014-05-06 15:04:28 -04001323
Nicolas Capens7551ac62016-01-20 17:11:53 -05001324 enableIndex++;
1325 enableStack[enableIndex] = condition;
John Bauman89401822014-05-06 15:04:28 -04001326
1327 llvm::BasicBlock *trueBlock = Nucleus::createBasicBlock();
1328 llvm::BasicBlock *falseBlock = Nucleus::createBasicBlock();
1329
John Bauman19bac1e2014-05-06 15:23:49 -04001330 Bool notAllFalse = SignMask(condition) != 0;
John Bauman89401822014-05-06 15:04:28 -04001331
1332 branch(notAllFalse, trueBlock, falseBlock);
1333
1334 isConditionalIf[ifDepth] = true;
1335 ifFalseBlock[ifDepth] = falseBlock;
1336
1337 ifDepth++;
1338 breakDepth++;
1339 }
1340
1341 void VertexProgram::LABEL(int labelIndex)
1342 {
John Bauman19bac1e2014-05-06 15:23:49 -04001343 if(!labelBlock[labelIndex])
1344 {
1345 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1346 }
1347
John Bauman89401822014-05-06 15:04:28 -04001348 Nucleus::setInsertBlock(labelBlock[labelIndex]);
John Bauman19bac1e2014-05-06 15:23:49 -04001349 currentLabel = labelIndex;
John Bauman89401822014-05-06 15:04:28 -04001350 }
1351
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001352 void VertexProgram::LOOP(const Src &integerRegister)
John Bauman89401822014-05-06 15:04:28 -04001353 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001354 loopDepth++;
John Bauman89401822014-05-06 15:04:28 -04001355
Nicolas Capens7551ac62016-01-20 17:11:53 -05001356 iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
1357 aL[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][1]));
1358 increment[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][2]));
John Bauman89401822014-05-06 15:04:28 -04001359
1360 // FIXME: Compiles to two instructions?
Nicolas Capens7551ac62016-01-20 17:11:53 -05001361 If(increment[loopDepth] == 0)
John Bauman89401822014-05-06 15:04:28 -04001362 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001363 increment[loopDepth] = 1;
John Bauman89401822014-05-06 15:04:28 -04001364 }
1365
1366 llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1367 llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1368 llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1369
1370 loopRepTestBlock[loopRepDepth] = testBlock;
1371 loopRepEndBlock[loopRepDepth] = endBlock;
1372
1373 // FIXME: jump(testBlock)
1374 Nucleus::createBr(testBlock);
1375 Nucleus::setInsertBlock(testBlock);
1376
Nicolas Capens7551ac62016-01-20 17:11:53 -05001377 branch(iteration[loopDepth] > 0, loopBlock, endBlock);
John Bauman89401822014-05-06 15:04:28 -04001378 Nucleus::setInsertBlock(loopBlock);
1379
Nicolas Capens7551ac62016-01-20 17:11:53 -05001380 iteration[loopDepth] = iteration[loopDepth] - 1; // FIXME: --
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001381
John Bauman89401822014-05-06 15:04:28 -04001382 loopRepDepth++;
1383 breakDepth = 0;
1384 }
1385
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001386 void VertexProgram::REP(const Src &integerRegister)
John Bauman89401822014-05-06 15:04:28 -04001387 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001388 loopDepth++;
John Bauman89401822014-05-06 15:04:28 -04001389
Nicolas Capens7551ac62016-01-20 17:11:53 -05001390 iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
1391 aL[loopDepth] = aL[loopDepth - 1];
John Bauman89401822014-05-06 15:04:28 -04001392
1393 llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1394 llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1395 llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1396
1397 loopRepTestBlock[loopRepDepth] = testBlock;
1398 loopRepEndBlock[loopRepDepth] = endBlock;
1399
1400 // FIXME: jump(testBlock)
1401 Nucleus::createBr(testBlock);
1402 Nucleus::setInsertBlock(testBlock);
1403
Nicolas Capens7551ac62016-01-20 17:11:53 -05001404 branch(iteration[loopDepth] > 0, loopBlock, endBlock);
John Bauman89401822014-05-06 15:04:28 -04001405 Nucleus::setInsertBlock(loopBlock);
1406
Nicolas Capens7551ac62016-01-20 17:11:53 -05001407 iteration[loopDepth] = iteration[loopDepth] - 1; // FIXME: --
John Bauman89401822014-05-06 15:04:28 -04001408
1409 loopRepDepth++;
1410 breakDepth = 0;
1411 }
1412
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001413 void VertexProgram::WHILE(const Src &temporaryRegister)
John Bauman19bac1e2014-05-06 15:23:49 -04001414 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001415 enableIndex++;
John Bauman19bac1e2014-05-06 15:23:49 -04001416
1417 llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1418 llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1419 llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001420
John Bauman19bac1e2014-05-06 15:23:49 -04001421 loopRepTestBlock[loopRepDepth] = testBlock;
1422 loopRepEndBlock[loopRepDepth] = endBlock;
1423
Nicolas Capens7551ac62016-01-20 17:11:53 -05001424 Int4 restoreBreak = enableBreak;
1425 Int4 restoreContinue = enableContinue;
John Bauman19bac1e2014-05-06 15:23:49 -04001426
1427 // FIXME: jump(testBlock)
1428 Nucleus::createBr(testBlock);
1429 Nucleus::setInsertBlock(testBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001430 enableContinue = restoreContinue;
John Bauman19bac1e2014-05-06 15:23:49 -04001431
Nicolas Capensc2534f42016-04-04 11:13:24 -04001432 const Vector4f &src = fetchRegister(temporaryRegister);
John Bauman19bac1e2014-05-06 15:23:49 -04001433 Int4 condition = As<Int4>(src.x);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001434 condition &= enableStack[enableIndex - 1];
1435 enableStack[enableIndex] = condition;
John Bauman19bac1e2014-05-06 15:23:49 -04001436
1437 Bool notAllFalse = SignMask(condition) != 0;
1438 branch(notAllFalse, loopBlock, endBlock);
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001439
John Bauman19bac1e2014-05-06 15:23:49 -04001440 Nucleus::setInsertBlock(endBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001441 enableBreak = restoreBreak;
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001442
John Bauman19bac1e2014-05-06 15:23:49 -04001443 Nucleus::setInsertBlock(loopBlock);
1444
1445 loopRepDepth++;
1446 breakDepth = 0;
1447 }
1448
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001449 void VertexProgram::RET()
John Bauman89401822014-05-06 15:04:28 -04001450 {
John Bauman19bac1e2014-05-06 15:23:49 -04001451 if(currentLabel == -1)
John Bauman89401822014-05-06 15:04:28 -04001452 {
1453 returnBlock = Nucleus::createBasicBlock();
1454 Nucleus::createBr(returnBlock);
John Bauman89401822014-05-06 15:04:28 -04001455 }
1456 else
1457 {
John Bauman89401822014-05-06 15:04:28 -04001458 llvm::BasicBlock *unreachableBlock = Nucleus::createBasicBlock();
John Bauman89401822014-05-06 15:04:28 -04001459
John Bauman19bac1e2014-05-06 15:23:49 -04001460 if(callRetBlock[currentLabel].size() > 1) // Pop the return destination from the call stack
John Bauman89401822014-05-06 15:04:28 -04001461 {
John Bauman19bac1e2014-05-06 15:23:49 -04001462 // FIXME: Encapsulate
Nicolas Capens7551ac62016-01-20 17:11:53 -05001463 UInt index = callStack[--stackIndex];
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001464
John Bauman66b8ab22014-05-06 15:57:45 -04001465 llvm::Value *value = index.loadValue();
John Bauman19bac1e2014-05-06 15:23:49 -04001466 llvm::Value *switchInst = Nucleus::createSwitch(value, unreachableBlock, (int)callRetBlock[currentLabel].size());
1467
1468 for(unsigned int i = 0; i < callRetBlock[currentLabel].size(); i++)
1469 {
1470 Nucleus::addSwitchCase(switchInst, i, callRetBlock[currentLabel][i]);
1471 }
1472 }
1473 else if(callRetBlock[currentLabel].size() == 1) // Jump directly to the unique return destination
1474 {
1475 Nucleus::createBr(callRetBlock[currentLabel][0]);
1476 }
1477 else // Function isn't called
1478 {
1479 Nucleus::createBr(unreachableBlock);
John Bauman89401822014-05-06 15:04:28 -04001480 }
1481
1482 Nucleus::setInsertBlock(unreachableBlock);
1483 Nucleus::createUnreachable();
1484 }
1485 }
1486
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001487 void VertexProgram::LEAVE()
John Bauman89401822014-05-06 15:04:28 -04001488 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001489 enableLeave = enableLeave & ~enableStack[enableIndex];
John Bauman89401822014-05-06 15:04:28 -04001490
John Bauman19bac1e2014-05-06 15:23:49 -04001491 // FIXME: Return from function if all instances left
1492 // FIXME: Use enableLeave in other control-flow constructs
1493 }
John Bauman89401822014-05-06 15:04:28 -04001494
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001495 void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1)
John Bauman19bac1e2014-05-06 15:23:49 -04001496 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001497 sampleTexture(dst, src1, src0.x, src0.y, src0.z, src0.w, Lod);
John Bauman89401822014-05-06 15:04:28 -04001498 }
John Bauman19bac1e2014-05-06 15:23:49 -04001499
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001500 void VertexProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1)
John Bauman19bac1e2014-05-06 15:23:49 -04001501 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001502 Float4 lod0 = Float4(0.0f);
1503 sampleTexture(dst, src1, src0.x, src0.y, src0.z, lod0, Lod);
John Bauman19bac1e2014-05-06 15:23:49 -04001504 }
1505
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001506 void VertexProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001507 {
1508 UNIMPLEMENTED();
1509 }
1510
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001511 void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src, const Src&, Vector4f &offset)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001512 {
1513 UNIMPLEMENTED();
1514 }
1515
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001516 void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001517 {
1518 UNIMPLEMENTED();
1519 }
1520
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001521 void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &offset)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001522 {
1523 UNIMPLEMENTED();
1524 }
1525
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001526 void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001527 {
1528 UNIMPLEMENTED();
1529 }
1530
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001531 void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3, Vector4f &offset)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001532 {
1533 UNIMPLEMENTED();
1534 }
1535
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001536 void VertexProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
Alexis Hetu9bcb31d2015-07-22 17:03:26 -04001537 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001538 Pointer<Byte> textureMipmap = data + OFFSET(DrawData, mipmap[16]) + src1.index * sizeof(Texture) + OFFSET(Texture, mipmap);
Alexis Hetu9bcb31d2015-07-22 17:03:26 -04001539 for(int i = 0; i < 4; ++i)
1540 {
1541 Pointer<Byte> mipmap = textureMipmap + (As<Int>(Extract(lod, i)) + Int(1)) * sizeof(Mipmap);
1542 dst.x = Insert(dst.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
1543 dst.y = Insert(dst.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
1544 dst.z = Insert(dst.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
1545 }
1546 }
1547
Nicolas Capensc2534f42016-04-04 11:13:24 -04001548 void VertexProgram::sampleTexture(Vector4f &c, const Src &s, Float4 &u, Float4 &v, Float4 &w, Float4 &q, SamplerMethod method)
John Bauman19bac1e2014-05-06 15:23:49 -04001549 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001550 Vector4f tmp;
1551
John Bauman19bac1e2014-05-06 15:23:49 -04001552 if(s.type == Shader::PARAMETER_SAMPLER && s.rel.type == Shader::PARAMETER_VOID)
1553 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001554 Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[TEXTURE_IMAGE_UNITS]) + s.index * sizeof(Texture);
1555 sampler[s.index]->sampleTexture(texture, tmp, u, v, w, q, a0, a0, method);
John Bauman19bac1e2014-05-06 15:23:49 -04001556 }
1557 else
1558 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001559 Int index = As<Int>(Float(fetchRegister(s).x.x));
John Bauman19bac1e2014-05-06 15:23:49 -04001560
Nicolas Capensc2534f42016-04-04 11:13:24 -04001561 for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
John Bauman19bac1e2014-05-06 15:23:49 -04001562 {
1563 if(shader->usesSampler(i))
1564 {
1565 If(index == i)
1566 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001567 Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[TEXTURE_IMAGE_UNITS]) + i * sizeof(Texture);
1568 sampler[i]->sampleTexture(texture, tmp, u, v, w, q, a0, a0, method);
John Bauman19bac1e2014-05-06 15:23:49 -04001569 // FIXME: When the sampler states are the same, we could use one sampler and just index the texture
1570 }
1571 }
1572 }
1573 }
Nicolas Capensc2534f42016-04-04 11:13:24 -04001574
1575 c.x = tmp[(s.swizzle >> 0) & 0x3];
1576 c.y = tmp[(s.swizzle >> 2) & 0x3];
1577 c.z = tmp[(s.swizzle >> 4) & 0x3];
1578 c.w = tmp[(s.swizzle >> 6) & 0x3];
John Bauman19bac1e2014-05-06 15:23:49 -04001579 }
John Bauman89401822014-05-06 15:04:28 -04001580}