blob: 1989c87fd9fde2f6d91113e86cb2c141b44b1e8a [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;
Alexis Hetu9cde9742016-04-06 13:03:38 -0400206 case Shader::OPCODE_PACKSNORM2x16: packSnorm2x16(d, s0); break;
207 case Shader::OPCODE_PACKUNORM2x16: packUnorm2x16(d, s0); break;
Alexis Hetuffb35eb2016-04-06 18:05:00 -0400208 case Shader::OPCODE_PACKHALF2x16: packHalf2x16(d, s0); break;
Alexis Hetu9cde9742016-04-06 13:03:38 -0400209 case Shader::OPCODE_UNPACKSNORM2x16: unpackSnorm2x16(d, s0); break;
210 case Shader::OPCODE_UNPACKUNORM2x16: unpackUnorm2x16(d, s0); break;
Alexis Hetuffb35eb2016-04-06 18:05:00 -0400211 case Shader::OPCODE_UNPACKHALF2x16: unpackHalf2x16(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500212 case Shader::OPCODE_M3X2: M3X2(d, s0, src1); break;
213 case Shader::OPCODE_M3X3: M3X3(d, s0, src1); break;
214 case Shader::OPCODE_M3X4: M3X4(d, s0, src1); break;
215 case Shader::OPCODE_M4X3: M4X3(d, s0, src1); break;
216 case Shader::OPCODE_M4X4: M4X4(d, s0, src1); break;
217 case Shader::OPCODE_MAD: mad(d, s0, s1, s2); break;
218 case Shader::OPCODE_IMAD: imad(d, s0, s1, s2); break;
219 case Shader::OPCODE_MAX: max(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400220 case Shader::OPCODE_IMAX: imax(d, s0, s1); break;
221 case Shader::OPCODE_UMAX: umax(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500222 case Shader::OPCODE_MIN: min(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400223 case Shader::OPCODE_IMIN: imin(d, s0, s1); break;
224 case Shader::OPCODE_UMIN: umin(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500225 case Shader::OPCODE_MOV: mov(d, s0, integer); break;
Alexis Hetu02a2bb82015-08-20 14:10:33 -0400226 case Shader::OPCODE_MOVA: mov(d, s0, true); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400227 case Shader::OPCODE_NEG: neg(d, s0); break;
228 case Shader::OPCODE_INEG: ineg(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500229 case Shader::OPCODE_F2B: f2b(d, s0); break;
230 case Shader::OPCODE_B2F: b2f(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400231 case Shader::OPCODE_F2I: f2i(d, s0); break;
232 case Shader::OPCODE_I2F: i2f(d, s0); break;
233 case Shader::OPCODE_F2U: f2u(d, s0); break;
234 case Shader::OPCODE_U2F: u2f(d, s0); break;
235 case Shader::OPCODE_I2B: i2b(d, s0); break;
236 case Shader::OPCODE_B2I: b2i(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500237 case Shader::OPCODE_MUL: mul(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400238 case Shader::OPCODE_IMUL: imul(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500239 case Shader::OPCODE_NRM2: nrm2(d, s0, pp); break;
240 case Shader::OPCODE_NRM3: nrm3(d, s0, pp); break;
241 case Shader::OPCODE_NRM4: nrm4(d, s0, pp); break;
242 case Shader::OPCODE_POWX: powx(d, s0, s1, pp); break;
243 case Shader::OPCODE_POW: pow(d, s0, s1, pp); break;
244 case Shader::OPCODE_RCPX: rcpx(d, s0, pp); break;
245 case Shader::OPCODE_DIV: div(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400246 case Shader::OPCODE_IDIV: idiv(d, s0, s1); break;
247 case Shader::OPCODE_UDIV: udiv(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500248 case Shader::OPCODE_MOD: mod(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400249 case Shader::OPCODE_IMOD: imod(d, s0, s1); break;
250 case Shader::OPCODE_UMOD: umod(d, s0, s1); break;
251 case Shader::OPCODE_SHL: shl(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500252 case Shader::OPCODE_ISHR: ishr(d, s0, s1); break;
253 case Shader::OPCODE_USHR: ushr(d, s0, s1); break;
254 case Shader::OPCODE_RSQX: rsqx(d, s0, pp); break;
255 case Shader::OPCODE_SQRT: sqrt(d, s0, pp); break;
256 case Shader::OPCODE_RSQ: rsq(d, s0, pp); break;
257 case Shader::OPCODE_LEN2: len2(d.x, s0, pp); break;
258 case Shader::OPCODE_LEN3: len3(d.x, s0, pp); break;
259 case Shader::OPCODE_LEN4: len4(d.x, s0, pp); break;
260 case Shader::OPCODE_DIST1: dist1(d.x, s0, s1, pp); break;
261 case Shader::OPCODE_DIST2: dist2(d.x, s0, s1, pp); break;
262 case Shader::OPCODE_DIST3: dist3(d.x, s0, s1, pp); break;
263 case Shader::OPCODE_DIST4: dist4(d.x, s0, s1, pp); break;
264 case Shader::OPCODE_SGE: step(d, s1, s0); break;
265 case Shader::OPCODE_SGN: sgn(d, s0); break;
Alexis Hetu0f448072016-03-18 10:56:08 -0400266 case Shader::OPCODE_ISGN: isgn(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500267 case Shader::OPCODE_SINCOS: sincos(d, s0, pp); break;
268 case Shader::OPCODE_COS: cos(d, s0, pp); break;
269 case Shader::OPCODE_SIN: sin(d, s0, pp); break;
270 case Shader::OPCODE_TAN: tan(d, s0); break;
271 case Shader::OPCODE_ACOS: acos(d, s0); break;
272 case Shader::OPCODE_ASIN: asin(d, s0); break;
273 case Shader::OPCODE_ATAN: atan(d, s0); break;
274 case Shader::OPCODE_ATAN2: atan2(d, s0, s1); break;
275 case Shader::OPCODE_COSH: cosh(d, s0, pp); break;
276 case Shader::OPCODE_SINH: sinh(d, s0, pp); break;
277 case Shader::OPCODE_TANH: tanh(d, s0, pp); break;
278 case Shader::OPCODE_ACOSH: acosh(d, s0, pp); break;
279 case Shader::OPCODE_ASINH: asinh(d, s0, pp); break;
280 case Shader::OPCODE_ATANH: atanh(d, s0, pp); break;
281 case Shader::OPCODE_SLT: slt(d, s0, s1); break;
282 case Shader::OPCODE_SUB: sub(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400283 case Shader::OPCODE_ISUB: isub(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500284 case Shader::OPCODE_BREAK: BREAK(); break;
285 case Shader::OPCODE_BREAKC: BREAKC(s0, s1, control); break;
286 case Shader::OPCODE_BREAKP: BREAKP(src0); break;
287 case Shader::OPCODE_CONTINUE: CONTINUE(); break;
288 case Shader::OPCODE_TEST: TEST(); break;
289 case Shader::OPCODE_CALL: CALL(dst.label, dst.callSite); break;
290 case Shader::OPCODE_CALLNZ: CALLNZ(dst.label, dst.callSite, src0); break;
291 case Shader::OPCODE_ELSE: ELSE(); break;
292 case Shader::OPCODE_ENDIF: ENDIF(); break;
293 case Shader::OPCODE_ENDLOOP: ENDLOOP(); break;
294 case Shader::OPCODE_ENDREP: ENDREP(); break;
295 case Shader::OPCODE_ENDWHILE: ENDWHILE(); break;
296 case Shader::OPCODE_IF: IF(src0); break;
297 case Shader::OPCODE_IFC: IFC(s0, s1, control); break;
298 case Shader::OPCODE_LABEL: LABEL(dst.index); break;
299 case Shader::OPCODE_LOOP: LOOP(src1); break;
300 case Shader::OPCODE_REP: REP(src0); break;
301 case Shader::OPCODE_WHILE: WHILE(src0); break;
302 case Shader::OPCODE_RET: RET(); break;
303 case Shader::OPCODE_LEAVE: LEAVE(); break;
304 case Shader::OPCODE_CMP: cmp(d, s0, s1, control); break;
305 case Shader::OPCODE_ICMP: icmp(d, s0, s1, control); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400306 case Shader::OPCODE_UCMP: ucmp(d, s0, s1, control); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500307 case Shader::OPCODE_SELECT: select(d, s0, s1, s2); break;
308 case Shader::OPCODE_EXTRACT: extract(d.x, s0, s1.x); break;
309 case Shader::OPCODE_INSERT: insert(d, s0, s1.x, s2.x); break;
310 case Shader::OPCODE_ALL: all(d.x, s0); break;
311 case Shader::OPCODE_ANY: any(d.x, s0); break;
312 case Shader::OPCODE_NOT: not(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400313 case Shader::OPCODE_OR: or(d, s0, s1); break;
314 case Shader::OPCODE_XOR: xor(d, s0, s1); break;
315 case Shader::OPCODE_AND: and(d, s0, s1); break;
316 case Shader::OPCODE_EQ: equal(d, s0, s1); break;
317 case Shader::OPCODE_NE: notEqual(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500318 case Shader::OPCODE_TEXLDL: TEXLDL(d, s0, src1); break;
319 case Shader::OPCODE_TEX: TEX(d, s0, src1); break;
320 case Shader::OPCODE_TEXOFFSET: TEXOFFSET(d, s0, src1, s2, s3); break;
321 case Shader::OPCODE_TEXLDLOFFSET: TEXLDL(d, s0, src1, s2); break;
322 case Shader::OPCODE_TEXELFETCH: TEXELFETCH(d, s0, src1, s2); break;
323 case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCH(d, s0, src1, s2, s3); break;
324 case Shader::OPCODE_TEXGRAD: TEXGRAD(d, s0, src1, s2, s3); break;
325 case Shader::OPCODE_TEXGRADOFFSET: TEXGRAD(d, s0, src1, s2, s3, s4); break;
326 case Shader::OPCODE_TEXSIZE: TEXSIZE(d, s0.x, src1); break;
327 case Shader::OPCODE_END: break;
John Bauman89401822014-05-06 15:04:28 -0400328 default:
329 ASSERT(false);
330 }
331
John Bauman19bac1e2014-05-06 15:23:49 -0400332 if(dst.type != Shader::PARAMETER_VOID && dst.type != Shader::PARAMETER_LABEL && opcode != Shader::OPCODE_NOP)
John Bauman89401822014-05-06 15:04:28 -0400333 {
John Bauman19bac1e2014-05-06 15:23:49 -0400334 if(dst.integer)
John Bauman89401822014-05-06 15:04:28 -0400335 {
John Bauman19bac1e2014-05-06 15:23:49 -0400336 switch(opcode)
337 {
338 case Shader::OPCODE_DIV:
339 if(dst.x) d.x = Trunc(d.x);
340 if(dst.y) d.y = Trunc(d.y);
341 if(dst.z) d.z = Trunc(d.z);
342 if(dst.w) d.w = Trunc(d.w);
343 break;
344 default:
345 break; // No truncation to integer required when arguments are integer
346 }
John Bauman89401822014-05-06 15:04:28 -0400347 }
348
John Bauman19bac1e2014-05-06 15:23:49 -0400349 if(dst.saturate)
John Bauman89401822014-05-06 15:04:28 -0400350 {
John Bauman19bac1e2014-05-06 15:23:49 -0400351 if(dst.x) d.x = Max(d.x, Float4(0.0f));
352 if(dst.y) d.y = Max(d.y, Float4(0.0f));
353 if(dst.z) d.z = Max(d.z, Float4(0.0f));
354 if(dst.w) d.w = Max(d.w, Float4(0.0f));
John Bauman89401822014-05-06 15:04:28 -0400355
John Bauman19bac1e2014-05-06 15:23:49 -0400356 if(dst.x) d.x = Min(d.x, Float4(1.0f));
357 if(dst.y) d.y = Min(d.y, Float4(1.0f));
358 if(dst.z) d.z = Min(d.z, Float4(1.0f));
359 if(dst.w) d.w = Min(d.w, Float4(1.0f));
360 }
361
Nicolas Capensc6e8ab12014-05-06 23:31:07 -0400362 if(instruction->isPredicated())
John Bauman19bac1e2014-05-06 15:23:49 -0400363 {
364 Vector4f pDst; // FIXME: Rename
365
366 switch(dst.type)
John Bauman89401822014-05-06 15:04:28 -0400367 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500368 case Shader::PARAMETER_VOID: break;
John Bauman19bac1e2014-05-06 15:23:49 -0400369 case Shader::PARAMETER_TEMP:
370 if(dst.rel.type == Shader::PARAMETER_VOID)
371 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500372 if(dst.x) pDst.x = r[dst.index].x;
373 if(dst.y) pDst.y = r[dst.index].y;
374 if(dst.z) pDst.z = r[dst.index].z;
375 if(dst.w) pDst.w = r[dst.index].w;
John Bauman19bac1e2014-05-06 15:23:49 -0400376 }
377 else
378 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500379 Int a = relativeAddress(dst);
John Bauman19bac1e2014-05-06 15:23:49 -0400380
Nicolas Capens7551ac62016-01-20 17:11:53 -0500381 if(dst.x) pDst.x = r[dst.index + a].x;
382 if(dst.y) pDst.y = r[dst.index + a].y;
383 if(dst.z) pDst.z = r[dst.index + a].z;
384 if(dst.w) pDst.w = r[dst.index + a].w;
John Bauman19bac1e2014-05-06 15:23:49 -0400385 }
386 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500387 case Shader::PARAMETER_ADDR: pDst = a0; break;
John Bauman19bac1e2014-05-06 15:23:49 -0400388 case Shader::PARAMETER_RASTOUT:
389 switch(dst.index)
John Bauman89401822014-05-06 15:04:28 -0400390 {
391 case 0:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500392 if(dst.x) pDst.x = o[Pos].x;
393 if(dst.y) pDst.y = o[Pos].y;
394 if(dst.z) pDst.z = o[Pos].z;
395 if(dst.w) pDst.w = o[Pos].w;
John Bauman89401822014-05-06 15:04:28 -0400396 break;
397 case 1:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500398 pDst.x = o[Fog].x;
John Bauman89401822014-05-06 15:04:28 -0400399 break;
400 case 2:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500401 pDst.x = o[Pts].y;
John Bauman89401822014-05-06 15:04:28 -0400402 break;
403 default:
404 ASSERT(false);
405 }
406 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400407 case Shader::PARAMETER_ATTROUT:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500408 if(dst.x) pDst.x = o[D0 + dst.index].x;
409 if(dst.y) pDst.y = o[D0 + dst.index].y;
410 if(dst.z) pDst.z = o[D0 + dst.index].z;
411 if(dst.w) pDst.w = o[D0 + dst.index].w;
John Bauman89401822014-05-06 15:04:28 -0400412 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400413 case Shader::PARAMETER_TEXCRDOUT:
414 // case Shader::PARAMETER_OUTPUT:
John Bauman89401822014-05-06 15:04:28 -0400415 if(version < 0x0300)
416 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500417 if(dst.x) pDst.x = o[T0 + dst.index].x;
418 if(dst.y) pDst.y = o[T0 + dst.index].y;
419 if(dst.z) pDst.z = o[T0 + dst.index].z;
420 if(dst.w) pDst.w = o[T0 + dst.index].w;
John Bauman89401822014-05-06 15:04:28 -0400421 }
422 else
423 {
John Bauman19bac1e2014-05-06 15:23:49 -0400424 if(dst.rel.type == Shader::PARAMETER_VOID) // Not relative
John Bauman89401822014-05-06 15:04:28 -0400425 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500426 if(dst.x) pDst.x = o[dst.index].x;
427 if(dst.y) pDst.y = o[dst.index].y;
428 if(dst.z) pDst.z = o[dst.index].z;
429 if(dst.w) pDst.w = o[dst.index].w;
John Bauman89401822014-05-06 15:04:28 -0400430 }
John Bauman19bac1e2014-05-06 15:23:49 -0400431 else
432 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500433 Int a = relativeAddress(dst);
John Bauman19bac1e2014-05-06 15:23:49 -0400434
Nicolas Capens7551ac62016-01-20 17:11:53 -0500435 if(dst.x) pDst.x = o[dst.index + a].x;
436 if(dst.y) pDst.y = o[dst.index + a].y;
437 if(dst.z) pDst.z = o[dst.index + a].z;
438 if(dst.w) pDst.w = o[dst.index + a].w;
John Bauman89401822014-05-06 15:04:28 -0400439 }
440 }
441 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500442 case Shader::PARAMETER_LABEL: break;
443 case Shader::PARAMETER_PREDICATE: pDst = p0; break;
444 case Shader::PARAMETER_INPUT: break;
John Bauman89401822014-05-06 15:04:28 -0400445 default:
446 ASSERT(false);
447 }
448
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500449 Int4 enable = enableMask(instruction);
John Bauman89401822014-05-06 15:04:28 -0400450
451 Int4 xEnable = enable;
452 Int4 yEnable = enable;
453 Int4 zEnable = enable;
454 Int4 wEnable = enable;
455
456 if(predicate)
457 {
John Bauman19bac1e2014-05-06 15:23:49 -0400458 unsigned char pSwizzle = instruction->predicateSwizzle;
John Bauman89401822014-05-06 15:04:28 -0400459
Nicolas Capens7551ac62016-01-20 17:11:53 -0500460 Float4 xPredicate = p0[(pSwizzle >> 0) & 0x03];
461 Float4 yPredicate = p0[(pSwizzle >> 2) & 0x03];
462 Float4 zPredicate = p0[(pSwizzle >> 4) & 0x03];
463 Float4 wPredicate = p0[(pSwizzle >> 6) & 0x03];
John Bauman89401822014-05-06 15:04:28 -0400464
John Bauman19bac1e2014-05-06 15:23:49 -0400465 if(!instruction->predicateNot)
John Bauman89401822014-05-06 15:04:28 -0400466 {
John Bauman19bac1e2014-05-06 15:23:49 -0400467 if(dst.x) xEnable = xEnable & As<Int4>(xPredicate);
468 if(dst.y) yEnable = yEnable & As<Int4>(yPredicate);
469 if(dst.z) zEnable = zEnable & As<Int4>(zPredicate);
470 if(dst.w) wEnable = wEnable & As<Int4>(wPredicate);
John Bauman89401822014-05-06 15:04:28 -0400471 }
472 else
473 {
John Bauman19bac1e2014-05-06 15:23:49 -0400474 if(dst.x) xEnable = xEnable & ~As<Int4>(xPredicate);
475 if(dst.y) yEnable = yEnable & ~As<Int4>(yPredicate);
476 if(dst.z) zEnable = zEnable & ~As<Int4>(zPredicate);
477 if(dst.w) wEnable = wEnable & ~As<Int4>(wPredicate);
John Bauman89401822014-05-06 15:04:28 -0400478 }
479 }
480
John Bauman19bac1e2014-05-06 15:23:49 -0400481 if(dst.x) d.x = As<Float4>(As<Int4>(d.x) & xEnable);
482 if(dst.y) d.y = As<Float4>(As<Int4>(d.y) & yEnable);
483 if(dst.z) d.z = As<Float4>(As<Int4>(d.z) & zEnable);
484 if(dst.w) d.w = As<Float4>(As<Int4>(d.w) & wEnable);
John Bauman89401822014-05-06 15:04:28 -0400485
John Bauman19bac1e2014-05-06 15:23:49 -0400486 if(dst.x) d.x = As<Float4>(As<Int4>(d.x) | (As<Int4>(pDst.x) & ~xEnable));
487 if(dst.y) d.y = As<Float4>(As<Int4>(d.y) | (As<Int4>(pDst.y) & ~yEnable));
488 if(dst.z) d.z = As<Float4>(As<Int4>(d.z) | (As<Int4>(pDst.z) & ~zEnable));
489 if(dst.w) d.w = As<Float4>(As<Int4>(d.w) | (As<Int4>(pDst.w) & ~wEnable));
John Bauman89401822014-05-06 15:04:28 -0400490 }
491
John Bauman19bac1e2014-05-06 15:23:49 -0400492 switch(dst.type)
John Bauman89401822014-05-06 15:04:28 -0400493 {
John Bauman19bac1e2014-05-06 15:23:49 -0400494 case Shader::PARAMETER_VOID:
John Bauman89401822014-05-06 15:04:28 -0400495 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400496 case Shader::PARAMETER_TEMP:
497 if(dst.rel.type == Shader::PARAMETER_VOID)
498 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500499 if(dst.x) r[dst.index].x = d.x;
500 if(dst.y) r[dst.index].y = d.y;
501 if(dst.z) r[dst.index].z = d.z;
502 if(dst.w) r[dst.index].w = d.w;
John Bauman19bac1e2014-05-06 15:23:49 -0400503 }
504 else
505 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500506 Int a = relativeAddress(dst);
John Bauman19bac1e2014-05-06 15:23:49 -0400507
Nicolas Capens7551ac62016-01-20 17:11:53 -0500508 if(dst.x) r[dst.index + a].x = d.x;
509 if(dst.y) r[dst.index + a].y = d.y;
510 if(dst.z) r[dst.index + a].z = d.z;
511 if(dst.w) r[dst.index + a].w = d.w;
John Bauman19bac1e2014-05-06 15:23:49 -0400512 }
John Bauman89401822014-05-06 15:04:28 -0400513 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400514 case Shader::PARAMETER_ADDR:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500515 if(dst.x) a0.x = d.x;
516 if(dst.y) a0.y = d.y;
517 if(dst.z) a0.z = d.z;
518 if(dst.w) a0.w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400519 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400520 case Shader::PARAMETER_RASTOUT:
521 switch(dst.index)
John Bauman89401822014-05-06 15:04:28 -0400522 {
523 case 0:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500524 if(dst.x) o[Pos].x = d.x;
525 if(dst.y) o[Pos].y = d.y;
526 if(dst.z) o[Pos].z = d.z;
527 if(dst.w) o[Pos].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400528 break;
529 case 1:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500530 o[Fog].x = d.x;
John Bauman89401822014-05-06 15:04:28 -0400531 break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500532 case 2:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500533 o[Pts].y = d.x;
John Bauman89401822014-05-06 15:04:28 -0400534 break;
535 default: ASSERT(false);
536 }
537 break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500538 case Shader::PARAMETER_ATTROUT:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500539 if(dst.x) o[D0 + dst.index].x = d.x;
540 if(dst.y) o[D0 + dst.index].y = d.y;
541 if(dst.z) o[D0 + dst.index].z = d.z;
542 if(dst.w) o[D0 + dst.index].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400543 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400544 case Shader::PARAMETER_TEXCRDOUT:
545 // case Shader::PARAMETER_OUTPUT:
John Bauman89401822014-05-06 15:04:28 -0400546 if(version < 0x0300)
547 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500548 if(dst.x) o[T0 + dst.index].x = d.x;
549 if(dst.y) o[T0 + dst.index].y = d.y;
550 if(dst.z) o[T0 + dst.index].z = d.z;
551 if(dst.w) o[T0 + dst.index].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400552 }
553 else
554 {
John Bauman19bac1e2014-05-06 15:23:49 -0400555 if(dst.rel.type == Shader::PARAMETER_VOID) // Not relative
John Bauman89401822014-05-06 15:04:28 -0400556 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500557 if(dst.x) o[dst.index].x = d.x;
558 if(dst.y) o[dst.index].y = d.y;
559 if(dst.z) o[dst.index].z = d.z;
560 if(dst.w) o[dst.index].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400561 }
John Bauman19bac1e2014-05-06 15:23:49 -0400562 else
563 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500564 Int a = relativeAddress(dst);
John Bauman19bac1e2014-05-06 15:23:49 -0400565
Nicolas Capens7551ac62016-01-20 17:11:53 -0500566 if(dst.x) o[dst.index + a].x = d.x;
567 if(dst.y) o[dst.index + a].y = d.y;
568 if(dst.z) o[dst.index + a].z = d.z;
569 if(dst.w) o[dst.index + a].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400570 }
571 }
572 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500573 case Shader::PARAMETER_LABEL: break;
574 case Shader::PARAMETER_PREDICATE: p0 = d; break;
575 case Shader::PARAMETER_INPUT: break;
John Bauman89401822014-05-06 15:04:28 -0400576 default:
577 ASSERT(false);
578 }
579 }
580 }
581
John Bauman19bac1e2014-05-06 15:23:49 -0400582 if(currentLabel != -1)
John Bauman89401822014-05-06 15:04:28 -0400583 {
584 Nucleus::setInsertBlock(returnBlock);
585 }
586 }
587
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500588 void VertexProgram::passThrough()
John Bauman89401822014-05-06 15:04:28 -0400589 {
John Bauman19bac1e2014-05-06 15:23:49 -0400590 if(shader)
John Bauman89401822014-05-06 15:04:28 -0400591 {
592 for(int i = 0; i < 12; i++)
593 {
John Bauman19bac1e2014-05-06 15:23:49 -0400594 unsigned char usage = shader->output[i][0].usage;
John Bauman89401822014-05-06 15:04:28 -0400595
596 switch(usage)
597 {
598 case 0xFF:
599 continue;
John Bauman19bac1e2014-05-06 15:23:49 -0400600 case Shader::USAGE_PSIZE:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500601 o[i].y = v[i].x;
John Bauman89401822014-05-06 15:04:28 -0400602 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400603 case Shader::USAGE_TEXCOORD:
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_POSITION:
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_COLOR:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500616 o[i].x = v[i].x;
617 o[i].y = v[i].y;
618 o[i].z = v[i].z;
619 o[i].w = v[i].w;
John Bauman89401822014-05-06 15:04:28 -0400620 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400621 case Shader::USAGE_FOG:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500622 o[i].x = v[i].x;
John Bauman89401822014-05-06 15:04:28 -0400623 break;
624 default:
625 ASSERT(false);
626 }
627 }
628 }
629 else
630 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500631 o[Pos].x = v[PositionT].x;
632 o[Pos].y = v[PositionT].y;
633 o[Pos].z = v[PositionT].z;
634 o[Pos].w = v[PositionT].w;
John Bauman89401822014-05-06 15:04:28 -0400635
636 for(int i = 0; i < 2; i++)
637 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500638 o[D0 + i].x = v[Color0 + i].x;
639 o[D0 + i].y = v[Color0 + i].y;
640 o[D0 + i].z = v[Color0 + i].z;
641 o[D0 + i].w = v[Color0 + i].w;
John Bauman89401822014-05-06 15:04:28 -0400642 }
643
644 for(int i = 0; i < 8; i++)
645 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500646 o[T0 + i].x = v[TexCoord0 + i].x;
647 o[T0 + i].y = v[TexCoord0 + i].y;
648 o[T0 + i].z = v[TexCoord0 + i].z;
649 o[T0 + i].w = v[TexCoord0 + i].w;
John Bauman89401822014-05-06 15:04:28 -0400650 }
651
Nicolas Capens7551ac62016-01-20 17:11:53 -0500652 o[Pts].y = v[PointSize].x;
John Bauman89401822014-05-06 15:04:28 -0400653 }
654 }
655
Nicolas Capensc2534f42016-04-04 11:13:24 -0400656 Vector4f VertexProgram::fetchRegister(const Src &src, unsigned int offset)
John Bauman89401822014-05-06 15:04:28 -0400657 {
John Bauman19bac1e2014-05-06 15:23:49 -0400658 Vector4f reg;
Nicolas Capens5d961882016-01-01 23:18:14 -0500659 unsigned int i = src.index + offset;
John Bauman89401822014-05-06 15:04:28 -0400660
John Bauman89401822014-05-06 15:04:28 -0400661 switch(src.type)
662 {
John Bauman19bac1e2014-05-06 15:23:49 -0400663 case Shader::PARAMETER_TEMP:
664 if(src.rel.type == Shader::PARAMETER_VOID)
665 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500666 reg = r[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400667 }
668 else
669 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400670 reg = r[i + relativeAddress(src, src.bufferIndex)];
John Bauman19bac1e2014-05-06 15:23:49 -0400671 }
672 break;
673 case Shader::PARAMETER_CONST:
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500674 reg = readConstant(src, offset);
John Bauman19bac1e2014-05-06 15:23:49 -0400675 break;
676 case Shader::PARAMETER_INPUT:
677 if(src.rel.type == Shader::PARAMETER_VOID)
678 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500679 reg = v[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400680 }
681 else
682 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400683 reg = v[i + relativeAddress(src, src.bufferIndex)];
John Bauman19bac1e2014-05-06 15:23:49 -0400684 }
685 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500686 case Shader::PARAMETER_VOID: return r[0]; // Dummy
John Bauman19bac1e2014-05-06 15:23:49 -0400687 case Shader::PARAMETER_FLOAT4LITERAL:
688 reg.x = Float4(src.value[0]);
689 reg.y = Float4(src.value[1]);
690 reg.z = Float4(src.value[2]);
691 reg.w = Float4(src.value[3]);
692 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500693 case Shader::PARAMETER_ADDR: reg = a0; break;
694 case Shader::PARAMETER_CONSTBOOL: return r[0]; // Dummy
695 case Shader::PARAMETER_CONSTINT: return r[0]; // Dummy
696 case Shader::PARAMETER_LOOP: return r[0]; // Dummy
697 case Shader::PARAMETER_PREDICATE: return r[0]; // Dummy
John Bauman19bac1e2014-05-06 15:23:49 -0400698 case Shader::PARAMETER_SAMPLER:
699 if(src.rel.type == Shader::PARAMETER_VOID)
700 {
701 reg.x = As<Float4>(Int4(i));
702 }
703 else if(src.rel.type == Shader::PARAMETER_TEMP)
704 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500705 reg.x = As<Float4>(Int4(i) + As<Int4>(r[src.rel.index].x));
John Bauman19bac1e2014-05-06 15:23:49 -0400706 }
707 return reg;
708 case Shader::PARAMETER_OUTPUT:
709 if(src.rel.type == Shader::PARAMETER_VOID)
710 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500711 reg = o[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400712 }
713 else
714 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400715 reg = o[i + relativeAddress(src, src.bufferIndex)];
John Bauman19bac1e2014-05-06 15:23:49 -0400716 }
717 break;
Alexis Hetudd8df682015-06-05 17:08:39 -0400718 case Shader::PARAMETER_MISCTYPE:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500719 reg.x = As<Float>(Int(instanceID));
Alexis Hetudd8df682015-06-05 17:08:39 -0400720 return reg;
John Bauman89401822014-05-06 15:04:28 -0400721 default:
722 ASSERT(false);
723 }
724
John Bauman66b8ab22014-05-06 15:57:45 -0400725 const Float4 &x = reg[(src.swizzle >> 0) & 0x3];
726 const Float4 &y = reg[(src.swizzle >> 2) & 0x3];
727 const Float4 &z = reg[(src.swizzle >> 4) & 0x3];
728 const Float4 &w = reg[(src.swizzle >> 6) & 0x3];
John Bauman89401822014-05-06 15:04:28 -0400729
John Bauman66b8ab22014-05-06 15:57:45 -0400730 Vector4f mod;
John Bauman89401822014-05-06 15:04:28 -0400731
732 switch(src.modifier)
733 {
John Bauman19bac1e2014-05-06 15:23:49 -0400734 case Shader::MODIFIER_NONE:
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_NEGATE:
John Bauman66b8ab22014-05-06 15:57:45 -0400741 mod.x = -x;
742 mod.y = -y;
743 mod.z = -z;
744 mod.w = -w;
John Bauman89401822014-05-06 15:04:28 -0400745 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400746 case Shader::MODIFIER_ABS:
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_ABS_NEGATE:
John Bauman66b8ab22014-05-06 15:57:45 -0400753 mod.x = -Abs(x);
754 mod.y = -Abs(y);
755 mod.z = -Abs(z);
756 mod.w = -Abs(w);
John Bauman89401822014-05-06 15:04:28 -0400757 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400758 case Shader::MODIFIER_NOT:
John Bauman66b8ab22014-05-06 15:57:45 -0400759 mod.x = As<Float4>(As<Int4>(x) ^ Int4(0xFFFFFFFF));
760 mod.y = As<Float4>(As<Int4>(y) ^ Int4(0xFFFFFFFF));
761 mod.z = As<Float4>(As<Int4>(z) ^ Int4(0xFFFFFFFF));
762 mod.w = As<Float4>(As<Int4>(w) ^ Int4(0xFFFFFFFF));
John Bauman89401822014-05-06 15:04:28 -0400763 break;
764 default:
765 ASSERT(false);
766 }
767
768 return mod;
769 }
770
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400771 RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index)
772 {
773 if(bufferIndex == -1)
774 {
775 return data + OFFSET(DrawData, vs.c[index]);
776 }
777 else
778 {
779 return *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.u[bufferIndex])) + index;
780 }
781 }
782
783 RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index, Int& offset)
784 {
785 return uniformAddress(bufferIndex, index) + offset * sizeof(float4);
786 }
787
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500788 Vector4f VertexProgram::readConstant(const Src &src, unsigned int offset)
John Bauman89401822014-05-06 15:04:28 -0400789 {
John Bauman19bac1e2014-05-06 15:23:49 -0400790 Vector4f c;
Nicolas Capens5d961882016-01-01 23:18:14 -0500791 unsigned int i = src.index + offset;
John Bauman19bac1e2014-05-06 15:23:49 -0400792
793 if(src.rel.type == Shader::PARAMETER_VOID) // Not relative
794 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400795 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i));
John Bauman19bac1e2014-05-06 15:23:49 -0400796
797 c.x = c.x.xxxx;
798 c.y = c.y.yyyy;
799 c.z = c.z.zzzz;
800 c.w = c.w.wwww;
801
Nicolas Capenseafdb222015-05-15 15:24:08 -0400802 if(shader->containsDefineInstruction()) // Constant may be known at compile time
John Bauman19bac1e2014-05-06 15:23:49 -0400803 {
Alexis Hetu903e0252014-11-25 14:25:32 -0500804 for(size_t j = 0; j < shader->getLength(); j++)
John Bauman19bac1e2014-05-06 15:23:49 -0400805 {
806 const Shader::Instruction &instruction = *shader->getInstruction(j);
807
808 if(instruction.opcode == Shader::OPCODE_DEF)
809 {
810 if(instruction.dst.index == i)
811 {
812 c.x = Float4(instruction.src[0].value[0]);
813 c.y = Float4(instruction.src[0].value[1]);
814 c.z = Float4(instruction.src[0].value[2]);
815 c.w = Float4(instruction.src[0].value[3]);
816
817 break;
818 }
819 }
820 }
821 }
822 }
823 else if(src.rel.type == Shader::PARAMETER_LOOP)
824 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500825 Int loopCounter = aL[loopDepth];
John Bauman19bac1e2014-05-06 15:23:49 -0400826
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400827 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, loopCounter));
John Bauman19bac1e2014-05-06 15:23:49 -0400828
829 c.x = c.x.xxxx;
830 c.y = c.y.yyyy;
831 c.z = c.z.zzzz;
832 c.w = c.w.wwww;
833 }
834 else
835 {
836 if(src.rel.deterministic)
837 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400838 Int a = relativeAddress(src, src.bufferIndex);
Nicolas Capensc2534f42016-04-04 11:13:24 -0400839
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400840 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, a));
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500841
John Bauman19bac1e2014-05-06 15:23:49 -0400842 c.x = c.x.xxxx;
843 c.y = c.y.yyyy;
844 c.z = c.z.zzzz;
845 c.w = c.w.wwww;
846 }
847 else
848 {
849 int component = src.rel.swizzle & 0x03;
850 Float4 a;
851
852 switch(src.rel.type)
853 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500854 case Shader::PARAMETER_ADDR: a = a0[component]; break;
855 case Shader::PARAMETER_TEMP: a = r[src.rel.index][component]; break;
856 case Shader::PARAMETER_INPUT: a = v[src.rel.index][component]; break;
857 case Shader::PARAMETER_OUTPUT: a = o[src.rel.index][component]; break;
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400858 case Shader::PARAMETER_CONST: a = *Pointer<Float>(uniformAddress(src.bufferIndex, src.rel.index) + component * sizeof(float)); break;
John Bauman19bac1e2014-05-06 15:23:49 -0400859 default: ASSERT(false);
860 }
861
Alexis Hetu02a2bb82015-08-20 14:10:33 -0400862 Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
John Bauman19bac1e2014-05-06 15:23:49 -0400863
Alexis Hetu028f41b2016-01-13 14:40:47 -0500864 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 -0500865
John Bauman19bac1e2014-05-06 15:23:49 -0400866 Int index0 = Extract(index, 0);
867 Int index1 = Extract(index, 1);
868 Int index2 = Extract(index, 2);
869 Int index3 = Extract(index, 3);
870
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400871 c.x = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index0), 16);
872 c.y = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index1), 16);
873 c.z = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index2), 16);
874 c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index3), 16);
John Bauman19bac1e2014-05-06 15:23:49 -0400875
876 transpose4x4(c.x, c.y, c.z, c.w);
877 }
878 }
879
880 return c;
881 }
882
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400883 Int VertexProgram::relativeAddress(const Shader::Parameter &var, int bufferIndex)
John Bauman19bac1e2014-05-06 15:23:49 -0400884 {
885 ASSERT(var.rel.deterministic);
886
887 if(var.rel.type == Shader::PARAMETER_TEMP)
888 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500889 return As<Int>(Extract(r[var.rel.index].x, 0)) * var.rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400890 }
891 else if(var.rel.type == Shader::PARAMETER_INPUT)
892 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500893 return As<Int>(Extract(v[var.rel.index].x, 0)) * var.rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400894 }
895 else if(var.rel.type == Shader::PARAMETER_OUTPUT)
896 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500897 return As<Int>(Extract(o[var.rel.index].x, 0)) * var.rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400898 }
899 else if(var.rel.type == Shader::PARAMETER_CONST)
900 {
Alexis Hetu48be7352016-02-10 14:32:34 -0500901 return *Pointer<Int>(uniformAddress(bufferIndex, var.rel.index)) * var.rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400902 }
Nicolas Capens907700d2016-01-20 17:09:28 -0500903 else if(var.rel.type == Shader::PARAMETER_LOOP)
904 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500905 return aL[loopDepth];
Nicolas Capens907700d2016-01-20 17:09:28 -0500906 }
John Bauman19bac1e2014-05-06 15:23:49 -0400907 else ASSERT(false);
908
909 return 0;
910 }
911
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500912 Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
John Bauman19bac1e2014-05-06 15:23:49 -0400913 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500914 Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500915
John Baumand4ae8632014-05-06 16:18:33 -0400916 if(!whileTest)
John Bauman19bac1e2014-05-06 15:23:49 -0400917 {
John Baumand4ae8632014-05-06 16:18:33 -0400918 if(shader->containsBreakInstruction() && instruction->analysisBreak)
919 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500920 enable &= enableBreak;
John Baumand4ae8632014-05-06 16:18:33 -0400921 }
John Bauman19bac1e2014-05-06 15:23:49 -0400922
John Baumand4ae8632014-05-06 16:18:33 -0400923 if(shader->containsContinueInstruction() && instruction->analysisContinue)
924 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500925 enable &= enableContinue;
John Baumand4ae8632014-05-06 16:18:33 -0400926 }
John Bauman19bac1e2014-05-06 15:23:49 -0400927
John Baumand4ae8632014-05-06 16:18:33 -0400928 if(shader->containsLeaveInstruction() && instruction->analysisLeave)
929 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500930 enable &= enableLeave;
John Baumand4ae8632014-05-06 16:18:33 -0400931 }
John Bauman19bac1e2014-05-06 15:23:49 -0400932 }
933
934 return enable;
935 }
936
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500937 void VertexProgram::M3X2(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman19bac1e2014-05-06 15:23:49 -0400938 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400939 Vector4f row0 = fetchRegister(src1, 0);
940 Vector4f row1 = fetchRegister(src1, 1);
John Bauman89401822014-05-06 15:04:28 -0400941
942 dst.x = dot3(src0, row0);
943 dst.y = dot3(src0, row1);
944 }
945
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500946 void VertexProgram::M3X3(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -0400947 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400948 Vector4f row0 = fetchRegister(src1, 0);
949 Vector4f row1 = fetchRegister(src1, 1);
950 Vector4f row2 = fetchRegister(src1, 2);
John Bauman89401822014-05-06 15:04:28 -0400951
952 dst.x = dot3(src0, row0);
953 dst.y = dot3(src0, row1);
954 dst.z = dot3(src0, row2);
955 }
956
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500957 void VertexProgram::M3X4(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -0400958 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400959 Vector4f row0 = fetchRegister(src1, 0);
960 Vector4f row1 = fetchRegister(src1, 1);
961 Vector4f row2 = fetchRegister(src1, 2);
962 Vector4f row3 = fetchRegister(src1, 3);
John Bauman89401822014-05-06 15:04:28 -0400963
964 dst.x = dot3(src0, row0);
965 dst.y = dot3(src0, row1);
966 dst.z = dot3(src0, row2);
967 dst.w = dot3(src0, row3);
968 }
969
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500970 void VertexProgram::M4X3(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -0400971 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400972 Vector4f row0 = fetchRegister(src1, 0);
973 Vector4f row1 = fetchRegister(src1, 1);
974 Vector4f row2 = fetchRegister(src1, 2);
John Bauman89401822014-05-06 15:04:28 -0400975
976 dst.x = dot4(src0, row0);
977 dst.y = dot4(src0, row1);
978 dst.z = dot4(src0, row2);
979 }
980
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500981 void VertexProgram::M4X4(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -0400982 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400983 Vector4f row0 = fetchRegister(src1, 0);
984 Vector4f row1 = fetchRegister(src1, 1);
985 Vector4f row2 = fetchRegister(src1, 2);
986 Vector4f row3 = fetchRegister(src1, 3);
John Bauman89401822014-05-06 15:04:28 -0400987
988 dst.x = dot4(src0, row0);
989 dst.y = dot4(src0, row1);
990 dst.z = dot4(src0, row2);
991 dst.w = dot4(src0, row3);
992 }
993
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500994 void VertexProgram::BREAK()
John Bauman89401822014-05-06 15:04:28 -0400995 {
996 llvm::BasicBlock *deadBlock = Nucleus::createBasicBlock();
997 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth - 1];
998
999 if(breakDepth == 0)
1000 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001001 enableIndex = enableIndex - breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001002 Nucleus::createBr(endBlock);
1003 }
1004 else
1005 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001006 enableBreak = enableBreak & ~enableStack[enableIndex];
1007 Bool allBreak = SignMask(enableBreak) == 0x0;
John Bauman89401822014-05-06 15:04:28 -04001008
Nicolas Capens7551ac62016-01-20 17:11:53 -05001009 enableIndex = enableIndex - breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001010 branch(allBreak, endBlock, deadBlock);
1011 }
1012
1013 Nucleus::setInsertBlock(deadBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001014 enableIndex = enableIndex + breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001015 }
1016
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001017 void VertexProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
John Bauman89401822014-05-06 15:04:28 -04001018 {
1019 Int4 condition;
1020
1021 switch(control)
1022 {
John Bauman19bac1e2014-05-06 15:23:49 -04001023 case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
1024 case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x); break;
1025 case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
1026 case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x); break;
1027 case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
1028 case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x); break;
John Bauman89401822014-05-06 15:04:28 -04001029 default:
1030 ASSERT(false);
1031 }
1032
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001033 BREAK(condition);
John Bauman89401822014-05-06 15:04:28 -04001034 }
1035
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001036 void VertexProgram::BREAKP(const Src &predicateRegister) // FIXME: Factor out parts common with BREAKC
John Bauman89401822014-05-06 15:04:28 -04001037 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001038 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001039
John Bauman19bac1e2014-05-06 15:23:49 -04001040 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001041 {
1042 condition = ~condition;
1043 }
1044
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001045 BREAK(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001046 }
1047
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001048 void VertexProgram::BREAK(Int4 &condition)
John Bauman19bac1e2014-05-06 15:23:49 -04001049 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001050 condition &= enableStack[enableIndex];
John Bauman89401822014-05-06 15:04:28 -04001051
1052 llvm::BasicBlock *continueBlock = Nucleus::createBasicBlock();
1053 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth - 1];
1054
Nicolas Capens7551ac62016-01-20 17:11:53 -05001055 enableBreak = enableBreak & ~condition;
1056 Bool allBreak = SignMask(enableBreak) == 0x0;
John Bauman89401822014-05-06 15:04:28 -04001057
Nicolas Capens7551ac62016-01-20 17:11:53 -05001058 enableIndex = enableIndex - breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001059 branch(allBreak, endBlock, continueBlock);
John Bauman19bac1e2014-05-06 15:23:49 -04001060
John Bauman89401822014-05-06 15:04:28 -04001061 Nucleus::setInsertBlock(continueBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001062 enableIndex = enableIndex + breakDepth;
John Bauman89401822014-05-06 15:04:28 -04001063 }
1064
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001065 void VertexProgram::CONTINUE()
John Bauman19bac1e2014-05-06 15:23:49 -04001066 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001067 enableContinue = enableContinue & ~enableStack[enableIndex];
John Bauman19bac1e2014-05-06 15:23:49 -04001068 }
1069
1070 void VertexProgram::TEST()
1071 {
1072 whileTest = true;
1073 }
1074
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001075 void VertexProgram::CALL(int labelIndex, int callSiteIndex)
John Bauman89401822014-05-06 15:04:28 -04001076 {
1077 if(!labelBlock[labelIndex])
1078 {
1079 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1080 }
1081
John Bauman19bac1e2014-05-06 15:23:49 -04001082 if(callRetBlock[labelIndex].size() > 1)
1083 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001084 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001085 }
John Bauman89401822014-05-06 15:04:28 -04001086
Nicolas Capens7551ac62016-01-20 17:11:53 -05001087 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001088
1089 Nucleus::createBr(labelBlock[labelIndex]);
John Bauman19bac1e2014-05-06 15:23:49 -04001090 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1091
Nicolas Capens7551ac62016-01-20 17:11:53 -05001092 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001093 }
1094
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001095 void VertexProgram::CALLNZ(int labelIndex, int callSiteIndex, const Src &src)
John Bauman89401822014-05-06 15:04:28 -04001096 {
John Bauman19bac1e2014-05-06 15:23:49 -04001097 if(src.type == Shader::PARAMETER_CONSTBOOL)
John Bauman89401822014-05-06 15:04:28 -04001098 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001099 CALLNZb(labelIndex, callSiteIndex, src);
John Bauman89401822014-05-06 15:04:28 -04001100 }
John Bauman19bac1e2014-05-06 15:23:49 -04001101 else if(src.type == Shader::PARAMETER_PREDICATE)
John Bauman89401822014-05-06 15:04:28 -04001102 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001103 CALLNZp(labelIndex, callSiteIndex, src);
John Bauman89401822014-05-06 15:04:28 -04001104 }
1105 else ASSERT(false);
1106 }
1107
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001108 void VertexProgram::CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister)
John Bauman89401822014-05-06 15:04:28 -04001109 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001110 Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0)); // FIXME
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001111
John Bauman19bac1e2014-05-06 15:23:49 -04001112 if(boolRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001113 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001114 condition = !condition;
John Bauman89401822014-05-06 15:04:28 -04001115 }
1116
1117 if(!labelBlock[labelIndex])
1118 {
1119 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1120 }
1121
John Bauman19bac1e2014-05-06 15:23:49 -04001122 if(callRetBlock[labelIndex].size() > 1)
1123 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001124 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001125 }
John Bauman89401822014-05-06 15:04:28 -04001126
Nicolas Capens7551ac62016-01-20 17:11:53 -05001127 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001128
John Bauman19bac1e2014-05-06 15:23:49 -04001129 branch(condition, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
1130 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1131
Nicolas Capens7551ac62016-01-20 17:11:53 -05001132 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001133 }
1134
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001135 void VertexProgram::CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister)
John Bauman89401822014-05-06 15:04:28 -04001136 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001137 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001138
John Bauman19bac1e2014-05-06 15:23:49 -04001139 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001140 {
1141 condition = ~condition;
1142 }
1143
Nicolas Capens7551ac62016-01-20 17:11:53 -05001144 condition &= enableStack[enableIndex];
John Bauman89401822014-05-06 15:04:28 -04001145
1146 if(!labelBlock[labelIndex])
1147 {
1148 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1149 }
1150
John Bauman19bac1e2014-05-06 15:23:49 -04001151 if(callRetBlock[labelIndex].size() > 1)
1152 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001153 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001154 }
John Bauman89401822014-05-06 15:04:28 -04001155
Nicolas Capens7551ac62016-01-20 17:11:53 -05001156 enableIndex++;
1157 enableStack[enableIndex] = condition;
1158 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001159
John Bauman19bac1e2014-05-06 15:23:49 -04001160 Bool notAllFalse = SignMask(condition) != 0;
1161 branch(notAllFalse, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
1162 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
John Bauman89401822014-05-06 15:04:28 -04001163
Nicolas Capens7551ac62016-01-20 17:11:53 -05001164 enableIndex--;
1165 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001166 }
1167
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001168 void VertexProgram::ELSE()
John Bauman89401822014-05-06 15:04:28 -04001169 {
1170 ifDepth--;
1171
1172 llvm::BasicBlock *falseBlock = ifFalseBlock[ifDepth];
1173 llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1174
1175 if(isConditionalIf[ifDepth])
1176 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001177 Int4 condition = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
John Bauman19bac1e2014-05-06 15:23:49 -04001178 Bool notAllFalse = SignMask(condition) != 0;
John Bauman89401822014-05-06 15:04:28 -04001179
1180 branch(notAllFalse, falseBlock, endBlock);
1181
Nicolas Capens7551ac62016-01-20 17:11:53 -05001182 enableStack[enableIndex] = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
John Bauman89401822014-05-06 15:04:28 -04001183 }
1184 else
1185 {
1186 Nucleus::createBr(endBlock);
1187 Nucleus::setInsertBlock(falseBlock);
1188 }
1189
1190 ifFalseBlock[ifDepth] = endBlock;
1191
1192 ifDepth++;
1193 }
1194
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001195 void VertexProgram::ENDIF()
John Bauman89401822014-05-06 15:04:28 -04001196 {
1197 ifDepth--;
1198
1199 llvm::BasicBlock *endBlock = ifFalseBlock[ifDepth];
1200
1201 Nucleus::createBr(endBlock);
1202 Nucleus::setInsertBlock(endBlock);
1203
1204 if(isConditionalIf[ifDepth])
1205 {
1206 breakDepth--;
Nicolas Capens7551ac62016-01-20 17:11:53 -05001207 enableIndex--;
John Bauman89401822014-05-06 15:04:28 -04001208 }
1209 }
1210
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001211 void VertexProgram::ENDLOOP()
John Bauman89401822014-05-06 15:04:28 -04001212 {
1213 loopRepDepth--;
1214
Nicolas Capens7551ac62016-01-20 17:11:53 -05001215 aL[loopDepth] = aL[loopDepth] + increment[loopDepth]; // FIXME: +=
John Bauman89401822014-05-06 15:04:28 -04001216
1217 llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1218 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1219
1220 Nucleus::createBr(testBlock);
1221 Nucleus::setInsertBlock(endBlock);
1222
Nicolas Capens7551ac62016-01-20 17:11:53 -05001223 loopDepth--;
1224 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
John Bauman89401822014-05-06 15:04:28 -04001225 }
1226
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001227 void VertexProgram::ENDREP()
John Bauman19bac1e2014-05-06 15:23:49 -04001228 {
1229 loopRepDepth--;
1230
1231 llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1232 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1233
1234 Nucleus::createBr(testBlock);
1235 Nucleus::setInsertBlock(endBlock);
1236
Nicolas Capens7551ac62016-01-20 17:11:53 -05001237 loopDepth--;
1238 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
John Bauman19bac1e2014-05-06 15:23:49 -04001239 }
1240
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001241 void VertexProgram::ENDWHILE()
John Bauman19bac1e2014-05-06 15:23:49 -04001242 {
1243 loopRepDepth--;
1244
1245 llvm::BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1246 llvm::BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
1247
1248 Nucleus::createBr(testBlock);
1249 Nucleus::setInsertBlock(endBlock);
1250
Nicolas Capens7551ac62016-01-20 17:11:53 -05001251 enableIndex--;
1252 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
John Bauman19bac1e2014-05-06 15:23:49 -04001253 whileTest = false;
1254 }
1255
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001256 void VertexProgram::IF(const Src &src)
John Bauman89401822014-05-06 15:04:28 -04001257 {
John Bauman19bac1e2014-05-06 15:23:49 -04001258 if(src.type == Shader::PARAMETER_CONSTBOOL)
John Bauman89401822014-05-06 15:04:28 -04001259 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001260 IFb(src);
John Bauman89401822014-05-06 15:04:28 -04001261 }
John Bauman19bac1e2014-05-06 15:23:49 -04001262 else if(src.type == Shader::PARAMETER_PREDICATE)
John Bauman89401822014-05-06 15:04:28 -04001263 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001264 IFp(src);
John Bauman89401822014-05-06 15:04:28 -04001265 }
John Bauman19bac1e2014-05-06 15:23:49 -04001266 else
1267 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001268 Int4 condition = As<Int4>(fetchRegister(src).x);
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001269 IF(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001270 }
John Bauman89401822014-05-06 15:04:28 -04001271 }
1272
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001273 void VertexProgram::IFb(const Src &boolRegister)
John Bauman89401822014-05-06 15:04:28 -04001274 {
1275 ASSERT(ifDepth < 24 + 4);
1276
Nicolas Capens7551ac62016-01-20 17:11:53 -05001277 Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0)); // FIXME
John Bauman89401822014-05-06 15:04:28 -04001278
John Bauman19bac1e2014-05-06 15:23:49 -04001279 if(boolRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001280 {
John Bauman19bac1e2014-05-06 15:23:49 -04001281 condition = !condition;
John Bauman89401822014-05-06 15:04:28 -04001282 }
1283
1284 llvm::BasicBlock *trueBlock = Nucleus::createBasicBlock();
1285 llvm::BasicBlock *falseBlock = Nucleus::createBasicBlock();
1286
1287 branch(condition, trueBlock, falseBlock);
1288
1289 isConditionalIf[ifDepth] = false;
1290 ifFalseBlock[ifDepth] = falseBlock;
1291
1292 ifDepth++;
1293 }
1294
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001295 void VertexProgram::IFp(const Src &predicateRegister)
John Bauman89401822014-05-06 15:04:28 -04001296 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001297 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001298
John Bauman19bac1e2014-05-06 15:23:49 -04001299 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001300 {
1301 condition = ~condition;
1302 }
1303
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001304 IF(condition);
John Bauman89401822014-05-06 15:04:28 -04001305 }
1306
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001307 void VertexProgram::IFC(Vector4f &src0, Vector4f &src1, Control control)
John Bauman89401822014-05-06 15:04:28 -04001308 {
1309 Int4 condition;
1310
1311 switch(control)
1312 {
John Bauman19bac1e2014-05-06 15:23:49 -04001313 case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
1314 case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x); break;
1315 case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
1316 case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x); break;
1317 case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
1318 case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x); break;
John Bauman89401822014-05-06 15:04:28 -04001319 default:
1320 ASSERT(false);
1321 }
1322
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001323 IF(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001324 }
1325
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001326 void VertexProgram::IF(Int4 &condition)
John Bauman19bac1e2014-05-06 15:23:49 -04001327 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001328 condition &= enableStack[enableIndex];
John Bauman89401822014-05-06 15:04:28 -04001329
Nicolas Capens7551ac62016-01-20 17:11:53 -05001330 enableIndex++;
1331 enableStack[enableIndex] = condition;
John Bauman89401822014-05-06 15:04:28 -04001332
1333 llvm::BasicBlock *trueBlock = Nucleus::createBasicBlock();
1334 llvm::BasicBlock *falseBlock = Nucleus::createBasicBlock();
1335
John Bauman19bac1e2014-05-06 15:23:49 -04001336 Bool notAllFalse = SignMask(condition) != 0;
John Bauman89401822014-05-06 15:04:28 -04001337
1338 branch(notAllFalse, trueBlock, falseBlock);
1339
1340 isConditionalIf[ifDepth] = true;
1341 ifFalseBlock[ifDepth] = falseBlock;
1342
1343 ifDepth++;
1344 breakDepth++;
1345 }
1346
1347 void VertexProgram::LABEL(int labelIndex)
1348 {
John Bauman19bac1e2014-05-06 15:23:49 -04001349 if(!labelBlock[labelIndex])
1350 {
1351 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1352 }
1353
John Bauman89401822014-05-06 15:04:28 -04001354 Nucleus::setInsertBlock(labelBlock[labelIndex]);
John Bauman19bac1e2014-05-06 15:23:49 -04001355 currentLabel = labelIndex;
John Bauman89401822014-05-06 15:04:28 -04001356 }
1357
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001358 void VertexProgram::LOOP(const Src &integerRegister)
John Bauman89401822014-05-06 15:04:28 -04001359 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001360 loopDepth++;
John Bauman89401822014-05-06 15:04:28 -04001361
Nicolas Capens7551ac62016-01-20 17:11:53 -05001362 iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
1363 aL[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][1]));
1364 increment[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][2]));
John Bauman89401822014-05-06 15:04:28 -04001365
1366 // FIXME: Compiles to two instructions?
Nicolas Capens7551ac62016-01-20 17:11:53 -05001367 If(increment[loopDepth] == 0)
John Bauman89401822014-05-06 15:04:28 -04001368 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001369 increment[loopDepth] = 1;
John Bauman89401822014-05-06 15:04:28 -04001370 }
1371
1372 llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1373 llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1374 llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1375
1376 loopRepTestBlock[loopRepDepth] = testBlock;
1377 loopRepEndBlock[loopRepDepth] = endBlock;
1378
1379 // FIXME: jump(testBlock)
1380 Nucleus::createBr(testBlock);
1381 Nucleus::setInsertBlock(testBlock);
1382
Nicolas Capens7551ac62016-01-20 17:11:53 -05001383 branch(iteration[loopDepth] > 0, loopBlock, endBlock);
John Bauman89401822014-05-06 15:04:28 -04001384 Nucleus::setInsertBlock(loopBlock);
1385
Nicolas Capens7551ac62016-01-20 17:11:53 -05001386 iteration[loopDepth] = iteration[loopDepth] - 1; // FIXME: --
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001387
John Bauman89401822014-05-06 15:04:28 -04001388 loopRepDepth++;
1389 breakDepth = 0;
1390 }
1391
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001392 void VertexProgram::REP(const Src &integerRegister)
John Bauman89401822014-05-06 15:04:28 -04001393 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001394 loopDepth++;
John Bauman89401822014-05-06 15:04:28 -04001395
Nicolas Capens7551ac62016-01-20 17:11:53 -05001396 iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
1397 aL[loopDepth] = aL[loopDepth - 1];
John Bauman89401822014-05-06 15:04:28 -04001398
1399 llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1400 llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1401 llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
1402
1403 loopRepTestBlock[loopRepDepth] = testBlock;
1404 loopRepEndBlock[loopRepDepth] = endBlock;
1405
1406 // FIXME: jump(testBlock)
1407 Nucleus::createBr(testBlock);
1408 Nucleus::setInsertBlock(testBlock);
1409
Nicolas Capens7551ac62016-01-20 17:11:53 -05001410 branch(iteration[loopDepth] > 0, loopBlock, endBlock);
John Bauman89401822014-05-06 15:04:28 -04001411 Nucleus::setInsertBlock(loopBlock);
1412
Nicolas Capens7551ac62016-01-20 17:11:53 -05001413 iteration[loopDepth] = iteration[loopDepth] - 1; // FIXME: --
John Bauman89401822014-05-06 15:04:28 -04001414
1415 loopRepDepth++;
1416 breakDepth = 0;
1417 }
1418
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001419 void VertexProgram::WHILE(const Src &temporaryRegister)
John Bauman19bac1e2014-05-06 15:23:49 -04001420 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001421 enableIndex++;
John Bauman19bac1e2014-05-06 15:23:49 -04001422
1423 llvm::BasicBlock *loopBlock = Nucleus::createBasicBlock();
1424 llvm::BasicBlock *testBlock = Nucleus::createBasicBlock();
1425 llvm::BasicBlock *endBlock = Nucleus::createBasicBlock();
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001426
John Bauman19bac1e2014-05-06 15:23:49 -04001427 loopRepTestBlock[loopRepDepth] = testBlock;
1428 loopRepEndBlock[loopRepDepth] = endBlock;
1429
Nicolas Capens7551ac62016-01-20 17:11:53 -05001430 Int4 restoreBreak = enableBreak;
1431 Int4 restoreContinue = enableContinue;
John Bauman19bac1e2014-05-06 15:23:49 -04001432
1433 // FIXME: jump(testBlock)
1434 Nucleus::createBr(testBlock);
1435 Nucleus::setInsertBlock(testBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001436 enableContinue = restoreContinue;
John Bauman19bac1e2014-05-06 15:23:49 -04001437
Nicolas Capensc2534f42016-04-04 11:13:24 -04001438 const Vector4f &src = fetchRegister(temporaryRegister);
John Bauman19bac1e2014-05-06 15:23:49 -04001439 Int4 condition = As<Int4>(src.x);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001440 condition &= enableStack[enableIndex - 1];
1441 enableStack[enableIndex] = condition;
John Bauman19bac1e2014-05-06 15:23:49 -04001442
1443 Bool notAllFalse = SignMask(condition) != 0;
1444 branch(notAllFalse, loopBlock, endBlock);
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001445
John Bauman19bac1e2014-05-06 15:23:49 -04001446 Nucleus::setInsertBlock(endBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001447 enableBreak = restoreBreak;
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001448
John Bauman19bac1e2014-05-06 15:23:49 -04001449 Nucleus::setInsertBlock(loopBlock);
1450
1451 loopRepDepth++;
1452 breakDepth = 0;
1453 }
1454
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001455 void VertexProgram::RET()
John Bauman89401822014-05-06 15:04:28 -04001456 {
John Bauman19bac1e2014-05-06 15:23:49 -04001457 if(currentLabel == -1)
John Bauman89401822014-05-06 15:04:28 -04001458 {
1459 returnBlock = Nucleus::createBasicBlock();
1460 Nucleus::createBr(returnBlock);
John Bauman89401822014-05-06 15:04:28 -04001461 }
1462 else
1463 {
John Bauman89401822014-05-06 15:04:28 -04001464 llvm::BasicBlock *unreachableBlock = Nucleus::createBasicBlock();
John Bauman89401822014-05-06 15:04:28 -04001465
John Bauman19bac1e2014-05-06 15:23:49 -04001466 if(callRetBlock[currentLabel].size() > 1) // Pop the return destination from the call stack
John Bauman89401822014-05-06 15:04:28 -04001467 {
John Bauman19bac1e2014-05-06 15:23:49 -04001468 // FIXME: Encapsulate
Nicolas Capens7551ac62016-01-20 17:11:53 -05001469 UInt index = callStack[--stackIndex];
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001470
John Bauman66b8ab22014-05-06 15:57:45 -04001471 llvm::Value *value = index.loadValue();
John Bauman19bac1e2014-05-06 15:23:49 -04001472 llvm::Value *switchInst = Nucleus::createSwitch(value, unreachableBlock, (int)callRetBlock[currentLabel].size());
1473
1474 for(unsigned int i = 0; i < callRetBlock[currentLabel].size(); i++)
1475 {
1476 Nucleus::addSwitchCase(switchInst, i, callRetBlock[currentLabel][i]);
1477 }
1478 }
1479 else if(callRetBlock[currentLabel].size() == 1) // Jump directly to the unique return destination
1480 {
1481 Nucleus::createBr(callRetBlock[currentLabel][0]);
1482 }
1483 else // Function isn't called
1484 {
1485 Nucleus::createBr(unreachableBlock);
John Bauman89401822014-05-06 15:04:28 -04001486 }
1487
1488 Nucleus::setInsertBlock(unreachableBlock);
1489 Nucleus::createUnreachable();
1490 }
1491 }
1492
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001493 void VertexProgram::LEAVE()
John Bauman89401822014-05-06 15:04:28 -04001494 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001495 enableLeave = enableLeave & ~enableStack[enableIndex];
John Bauman89401822014-05-06 15:04:28 -04001496
John Bauman19bac1e2014-05-06 15:23:49 -04001497 // FIXME: Return from function if all instances left
1498 // FIXME: Use enableLeave in other control-flow constructs
1499 }
John Bauman89401822014-05-06 15:04:28 -04001500
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001501 void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1)
John Bauman19bac1e2014-05-06 15:23:49 -04001502 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001503 sampleTexture(dst, src1, src0.x, src0.y, src0.z, src0.w, Lod);
John Bauman89401822014-05-06 15:04:28 -04001504 }
John Bauman19bac1e2014-05-06 15:23:49 -04001505
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001506 void VertexProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1)
John Bauman19bac1e2014-05-06 15:23:49 -04001507 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001508 Float4 lod0 = Float4(0.0f);
1509 sampleTexture(dst, src1, src0.x, src0.y, src0.z, lod0, Lod);
John Bauman19bac1e2014-05-06 15:23:49 -04001510 }
1511
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001512 void VertexProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001513 {
1514 UNIMPLEMENTED();
1515 }
1516
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001517 void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src, const Src&, Vector4f &offset)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001518 {
1519 UNIMPLEMENTED();
1520 }
1521
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001522 void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001523 {
1524 UNIMPLEMENTED();
1525 }
1526
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001527 void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &offset)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001528 {
1529 UNIMPLEMENTED();
1530 }
1531
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001532 void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001533 {
1534 UNIMPLEMENTED();
1535 }
1536
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001537 void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3, Vector4f &offset)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001538 {
1539 UNIMPLEMENTED();
1540 }
1541
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001542 void VertexProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
Alexis Hetu9bcb31d2015-07-22 17:03:26 -04001543 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001544 Pointer<Byte> textureMipmap = data + OFFSET(DrawData, mipmap[16]) + src1.index * sizeof(Texture) + OFFSET(Texture, mipmap);
Alexis Hetu9bcb31d2015-07-22 17:03:26 -04001545 for(int i = 0; i < 4; ++i)
1546 {
1547 Pointer<Byte> mipmap = textureMipmap + (As<Int>(Extract(lod, i)) + Int(1)) * sizeof(Mipmap);
1548 dst.x = Insert(dst.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
1549 dst.y = Insert(dst.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
1550 dst.z = Insert(dst.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
1551 }
1552 }
1553
Nicolas Capensc2534f42016-04-04 11:13:24 -04001554 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 -04001555 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001556 Vector4f tmp;
1557
John Bauman19bac1e2014-05-06 15:23:49 -04001558 if(s.type == Shader::PARAMETER_SAMPLER && s.rel.type == Shader::PARAMETER_VOID)
1559 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001560 Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[TEXTURE_IMAGE_UNITS]) + s.index * sizeof(Texture);
1561 sampler[s.index]->sampleTexture(texture, tmp, u, v, w, q, a0, a0, method);
John Bauman19bac1e2014-05-06 15:23:49 -04001562 }
1563 else
1564 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001565 Int index = As<Int>(Float(fetchRegister(s).x.x));
John Bauman19bac1e2014-05-06 15:23:49 -04001566
Nicolas Capensc2534f42016-04-04 11:13:24 -04001567 for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
John Bauman19bac1e2014-05-06 15:23:49 -04001568 {
1569 if(shader->usesSampler(i))
1570 {
1571 If(index == i)
1572 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001573 Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[TEXTURE_IMAGE_UNITS]) + i * sizeof(Texture);
1574 sampler[i]->sampleTexture(texture, tmp, u, v, w, q, a0, a0, method);
John Bauman19bac1e2014-05-06 15:23:49 -04001575 // FIXME: When the sampler states are the same, we could use one sampler and just index the texture
1576 }
1577 }
1578 }
1579 }
Nicolas Capensc2534f42016-04-04 11:13:24 -04001580
1581 c.x = tmp[(s.swizzle >> 0) & 0x3];
1582 c.y = tmp[(s.swizzle >> 2) & 0x3];
1583 c.z = tmp[(s.swizzle >> 4) & 0x3];
1584 c.w = tmp[(s.swizzle >> 6) & 0x3];
John Bauman19bac1e2014-05-06 15:23:49 -04001585 }
John Bauman89401822014-05-06 15:04:28 -04001586}