blob: 0463ea619003f5ceb53e1ba989b47415e936bd1c [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "VertexProgram.hpp"
16
John Bauman89401822014-05-06 15:04:28 -040017#include "VertexShader.hpp"
John Bauman89401822014-05-06 15:04:28 -040018#include "SamplerCore.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040019#include "Renderer/Renderer.hpp"
20#include "Renderer/Vertex.hpp"
21#include "Common/Half.hpp"
22#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040023
John Bauman89401822014-05-06 15:04:28 -040024namespace sw
25{
Nicolas Capens7551ac62016-01-20 17:11:53 -050026 VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader)
Ben Claytond951f192019-02-11 20:59:19 +000027 : VertexRoutine(state, shader),
28 shader(shader),
29 r(shader->indirectAddressableTemporaries),
30 aL(shader->getLimits().loops),
31 increment(shader->getLimits().loops),
32 iteration(shader->getLimits().loops),
33 callStack(shader->getLimits().stack)
John Bauman89401822014-05-06 15:04:28 -040034 {
Ben Claytond951f192019-02-11 20:59:19 +000035 auto limits = shader->getLimits();
36 ifDepth.setLimit(limits.ifs);
37 loopRepDepth.setLimit(limits.loops);
38 currentLabel.setLimit(limits.functions);
39
40 ifFalseBlock.resize(limits.ifs);
41 loopRepTestBlock.resize(limits.loops);
42 loopRepEndBlock.resize(limits.loops);
43 labelBlock.resize(limits.functions);
44 isConditionalIf.resize(limits.ifs);
Nicolas Capens7551ac62016-01-20 17:11:53 -050045
46 loopDepth = -1;
47 enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
48
Nicolas Capensc62fad32018-01-26 01:55:31 +000049 if(shader->containsBreakInstruction())
Nicolas Capens7551ac62016-01-20 17:11:53 -050050 {
51 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
52 }
53
Nicolas Capensc62fad32018-01-26 01:55:31 +000054 if(shader->containsContinueInstruction())
Nicolas Capens7551ac62016-01-20 17:11:53 -050055 {
56 enableContinue = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
57 }
58
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040059 if(shader->isInstanceIdDeclared())
Nicolas Capens7551ac62016-01-20 17:11:53 -050060 {
61 instanceID = *Pointer<Int>(data + OFFSET(DrawData,instanceID));
62 }
John Bauman89401822014-05-06 15:04:28 -040063 }
64
65 VertexProgram::~VertexProgram()
66 {
John Bauman89401822014-05-06 15:04:28 -040067 }
68
Nicolas Capens4b743732018-05-28 13:22:07 -040069 void VertexProgram::pipeline(UInt &index)
John Bauman89401822014-05-06 15:04:28 -040070 {
John Bauman89401822014-05-06 15:04:28 -040071 if(!state.preTransformed)
72 {
Alexis Hetu877ddfc2017-07-25 17:48:00 -040073 program(index);
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 Capens4b743732018-05-28 13:22:07 -040081 void VertexProgram::program(UInt &index)
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
Alexis Hetu53ad4af2017-12-06 14:49:07 -050085 unsigned short shaderModel = shader->getShaderModel();
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
Alexis Hetu877ddfc2017-07-25 17:48:00 -040095 if(shader->isVertexIdDeclared())
96 {
97 if(state.textureSampling)
98 {
99 vertexID = Int4(index);
100 }
101 else
102 {
103 vertexID = Insert(vertexID, As<Int>(index), 0);
104 vertexID = Insert(vertexID, As<Int>(index + 1), 1);
105 vertexID = Insert(vertexID, As<Int>(index + 2), 2);
106 vertexID = Insert(vertexID, As<Int>(index + 3), 3);
107 }
108 }
109
John Bauman19bac1e2014-05-06 15:23:49 -0400110 // Create all call site return blocks up front
Alexis Hetu903e0252014-11-25 14:25:32 -0500111 for(size_t i = 0; i < shader->getLength(); i++)
John Bauman89401822014-05-06 15:04:28 -0400112 {
John Bauman19bac1e2014-05-06 15:23:49 -0400113 const Shader::Instruction *instruction = shader->getInstruction(i);
114 Shader::Opcode opcode = instruction->opcode;
John Bauman89401822014-05-06 15:04:28 -0400115
John Bauman19bac1e2014-05-06 15:23:49 -0400116 if(opcode == Shader::OPCODE_CALL || opcode == Shader::OPCODE_CALLNZ)
117 {
118 const Dst &dst = instruction->dst;
John Bauman89401822014-05-06 15:04:28 -0400119
John Bauman19bac1e2014-05-06 15:23:49 -0400120 ASSERT(callRetBlock[dst.label].size() == dst.callSite);
121 callRetBlock[dst.label].push_back(Nucleus::createBasicBlock());
122 }
123 }
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500124
Alexis Hetu903e0252014-11-25 14:25:32 -0500125 for(size_t i = 0; i < shader->getLength(); i++)
John Bauman19bac1e2014-05-06 15:23:49 -0400126 {
127 const Shader::Instruction *instruction = shader->getInstruction(i);
128 Shader::Opcode opcode = instruction->opcode;
129
130 if(opcode == Shader::OPCODE_DCL || opcode == Shader::OPCODE_DEF || opcode == Shader::OPCODE_DEFI || opcode == Shader::OPCODE_DEFB)
John Bauman89401822014-05-06 15:04:28 -0400131 {
132 continue;
133 }
134
John Bauman19bac1e2014-05-06 15:23:49 -0400135 Dst dst = instruction->dst;
136 Src src0 = instruction->src[0];
137 Src src1 = instruction->src[1];
138 Src src2 = instruction->src[2];
Alexis Hetuc3d95f32015-09-23 12:27:32 -0400139 Src src3 = instruction->src[3];
Alexis Hetu25d47fc2015-10-22 13:58:32 -0400140 Src src4 = instruction->src[4];
John Bauman89401822014-05-06 15:04:28 -0400141
John Bauman19bac1e2014-05-06 15:23:49 -0400142 bool predicate = instruction->predicate;
John Bauman19bac1e2014-05-06 15:23:49 -0400143 Control control = instruction->control;
144 bool integer = dst.type == Shader::PARAMETER_ADDR;
145 bool pp = dst.partialPrecision;
John Bauman89401822014-05-06 15:04:28 -0400146
John Bauman19bac1e2014-05-06 15:23:49 -0400147 Vector4f d;
148 Vector4f s0;
149 Vector4f s1;
150 Vector4f s2;
Alexis Hetuc3d95f32015-09-23 12:27:32 -0400151 Vector4f s3;
Alexis Hetu25d47fc2015-10-22 13:58:32 -0400152 Vector4f s4;
John Bauman89401822014-05-06 15:04:28 -0400153
Nicolas Capensc2534f42016-04-04 11:13:24 -0400154 if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
155 if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
156 if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
157 if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegister(src3);
158 if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegister(src4);
John Bauman89401822014-05-06 15:04:28 -0400159
160 switch(opcode)
161 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500162 case Shader::OPCODE_VS_1_0: break;
163 case Shader::OPCODE_VS_1_1: break;
164 case Shader::OPCODE_VS_2_0: break;
165 case Shader::OPCODE_VS_2_x: break;
166 case Shader::OPCODE_VS_2_sw: break;
167 case Shader::OPCODE_VS_3_0: break;
168 case Shader::OPCODE_VS_3_sw: break;
169 case Shader::OPCODE_DCL: break;
170 case Shader::OPCODE_DEF: break;
171 case Shader::OPCODE_DEFI: break;
172 case Shader::OPCODE_DEFB: break;
173 case Shader::OPCODE_NOP: break;
174 case Shader::OPCODE_ABS: abs(d, s0); break;
Alexis Hetu0f448072016-03-18 10:56:08 -0400175 case Shader::OPCODE_IABS: iabs(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500176 case Shader::OPCODE_ADD: add(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400177 case Shader::OPCODE_IADD: iadd(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500178 case Shader::OPCODE_CRS: crs(d, s0, s1); break;
179 case Shader::OPCODE_FORWARD1: forward1(d, s0, s1, s2); break;
180 case Shader::OPCODE_FORWARD2: forward2(d, s0, s1, s2); break;
181 case Shader::OPCODE_FORWARD3: forward3(d, s0, s1, s2); break;
182 case Shader::OPCODE_FORWARD4: forward4(d, s0, s1, s2); break;
183 case Shader::OPCODE_REFLECT1: reflect1(d, s0, s1); break;
184 case Shader::OPCODE_REFLECT2: reflect2(d, s0, s1); break;
185 case Shader::OPCODE_REFLECT3: reflect3(d, s0, s1); break;
186 case Shader::OPCODE_REFLECT4: reflect4(d, s0, s1); break;
187 case Shader::OPCODE_REFRACT1: refract1(d, s0, s1, s2.x); break;
188 case Shader::OPCODE_REFRACT2: refract2(d, s0, s1, s2.x); break;
189 case Shader::OPCODE_REFRACT3: refract3(d, s0, s1, s2.x); break;
190 case Shader::OPCODE_REFRACT4: refract4(d, s0, s1, s2.x); break;
191 case Shader::OPCODE_DP1: dp1(d, s0, s1); break;
192 case Shader::OPCODE_DP2: dp2(d, s0, s1); break;
193 case Shader::OPCODE_DP3: dp3(d, s0, s1); break;
194 case Shader::OPCODE_DP4: dp4(d, s0, s1); break;
Alexis Hetuc3d95f32015-09-23 12:27:32 -0400195 case Shader::OPCODE_DET2: det2(d, s0, s1); break;
196 case Shader::OPCODE_DET3: det3(d, s0, s1, s2); break;
197 case Shader::OPCODE_DET4: det4(d, s0, s1, s2, s3); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500198 case Shader::OPCODE_ATT: att(d, s0, s1); break;
199 case Shader::OPCODE_EXP2X: exp2x(d, s0, pp); break;
200 case Shader::OPCODE_EXP2: exp2(d, s0, pp); break;
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500201 case Shader::OPCODE_EXPP: expp(d, s0, shaderModel); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500202 case Shader::OPCODE_EXP: exp(d, s0, pp); break;
203 case Shader::OPCODE_FRC: frc(d, s0); break;
John Bauman19bac1e2014-05-06 15:23:49 -0400204 case Shader::OPCODE_TRUNC: trunc(d, s0); break;
205 case Shader::OPCODE_FLOOR: floor(d, s0); break;
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400206 case Shader::OPCODE_ROUND: round(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500207 case Shader::OPCODE_ROUNDEVEN: roundEven(d, s0); break;
John Bauman19bac1e2014-05-06 15:23:49 -0400208 case Shader::OPCODE_CEIL: ceil(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500209 case Shader::OPCODE_LIT: lit(d, s0); break;
210 case Shader::OPCODE_LOG2X: log2x(d, s0, pp); break;
211 case Shader::OPCODE_LOG2: log2(d, s0, pp); break;
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500212 case Shader::OPCODE_LOGP: logp(d, s0, shaderModel); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500213 case Shader::OPCODE_LOG: log(d, s0, pp); break;
214 case Shader::OPCODE_LRP: lrp(d, s0, s1, s2); break;
215 case Shader::OPCODE_STEP: step(d, s0, s1); break;
216 case Shader::OPCODE_SMOOTH: smooth(d, s0, s1, s2); break;
Alexis Hetu8ef6d102017-11-09 15:49:09 -0500217 case Shader::OPCODE_ISINF: isinf(d, s0); break;
218 case Shader::OPCODE_ISNAN: isnan(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400219 case Shader::OPCODE_FLOATBITSTOINT:
220 case Shader::OPCODE_FLOATBITSTOUINT:
221 case Shader::OPCODE_INTBITSTOFLOAT:
222 case Shader::OPCODE_UINTBITSTOFLOAT: d = s0; break;
Alexis Hetu9cde9742016-04-06 13:03:38 -0400223 case Shader::OPCODE_PACKSNORM2x16: packSnorm2x16(d, s0); break;
224 case Shader::OPCODE_PACKUNORM2x16: packUnorm2x16(d, s0); break;
Alexis Hetuffb35eb2016-04-06 18:05:00 -0400225 case Shader::OPCODE_PACKHALF2x16: packHalf2x16(d, s0); break;
Alexis Hetu9cde9742016-04-06 13:03:38 -0400226 case Shader::OPCODE_UNPACKSNORM2x16: unpackSnorm2x16(d, s0); break;
227 case Shader::OPCODE_UNPACKUNORM2x16: unpackUnorm2x16(d, s0); break;
Alexis Hetuffb35eb2016-04-06 18:05:00 -0400228 case Shader::OPCODE_UNPACKHALF2x16: unpackHalf2x16(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500229 case Shader::OPCODE_M3X2: M3X2(d, s0, src1); break;
230 case Shader::OPCODE_M3X3: M3X3(d, s0, src1); break;
231 case Shader::OPCODE_M3X4: M3X4(d, s0, src1); break;
232 case Shader::OPCODE_M4X3: M4X3(d, s0, src1); break;
233 case Shader::OPCODE_M4X4: M4X4(d, s0, src1); break;
234 case Shader::OPCODE_MAD: mad(d, s0, s1, s2); break;
235 case Shader::OPCODE_IMAD: imad(d, s0, s1, s2); break;
236 case Shader::OPCODE_MAX: max(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400237 case Shader::OPCODE_IMAX: imax(d, s0, s1); break;
238 case Shader::OPCODE_UMAX: umax(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500239 case Shader::OPCODE_MIN: min(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400240 case Shader::OPCODE_IMIN: imin(d, s0, s1); break;
241 case Shader::OPCODE_UMIN: umin(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500242 case Shader::OPCODE_MOV: mov(d, s0, integer); break;
Alexis Hetu02a2bb82015-08-20 14:10:33 -0400243 case Shader::OPCODE_MOVA: mov(d, s0, true); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400244 case Shader::OPCODE_NEG: neg(d, s0); break;
245 case Shader::OPCODE_INEG: ineg(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500246 case Shader::OPCODE_F2B: f2b(d, s0); break;
247 case Shader::OPCODE_B2F: b2f(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400248 case Shader::OPCODE_F2I: f2i(d, s0); break;
249 case Shader::OPCODE_I2F: i2f(d, s0); break;
250 case Shader::OPCODE_F2U: f2u(d, s0); break;
251 case Shader::OPCODE_U2F: u2f(d, s0); break;
252 case Shader::OPCODE_I2B: i2b(d, s0); break;
253 case Shader::OPCODE_B2I: b2i(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500254 case Shader::OPCODE_MUL: mul(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400255 case Shader::OPCODE_IMUL: imul(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500256 case Shader::OPCODE_NRM2: nrm2(d, s0, pp); break;
257 case Shader::OPCODE_NRM3: nrm3(d, s0, pp); break;
258 case Shader::OPCODE_NRM4: nrm4(d, s0, pp); break;
259 case Shader::OPCODE_POWX: powx(d, s0, s1, pp); break;
260 case Shader::OPCODE_POW: pow(d, s0, s1, pp); break;
261 case Shader::OPCODE_RCPX: rcpx(d, s0, pp); break;
262 case Shader::OPCODE_DIV: div(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400263 case Shader::OPCODE_IDIV: idiv(d, s0, s1); break;
264 case Shader::OPCODE_UDIV: udiv(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500265 case Shader::OPCODE_MOD: mod(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400266 case Shader::OPCODE_IMOD: imod(d, s0, s1); break;
267 case Shader::OPCODE_UMOD: umod(d, s0, s1); break;
268 case Shader::OPCODE_SHL: shl(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500269 case Shader::OPCODE_ISHR: ishr(d, s0, s1); break;
270 case Shader::OPCODE_USHR: ushr(d, s0, s1); break;
271 case Shader::OPCODE_RSQX: rsqx(d, s0, pp); break;
272 case Shader::OPCODE_SQRT: sqrt(d, s0, pp); break;
273 case Shader::OPCODE_RSQ: rsq(d, s0, pp); break;
274 case Shader::OPCODE_LEN2: len2(d.x, s0, pp); break;
275 case Shader::OPCODE_LEN3: len3(d.x, s0, pp); break;
276 case Shader::OPCODE_LEN4: len4(d.x, s0, pp); break;
277 case Shader::OPCODE_DIST1: dist1(d.x, s0, s1, pp); break;
278 case Shader::OPCODE_DIST2: dist2(d.x, s0, s1, pp); break;
279 case Shader::OPCODE_DIST3: dist3(d.x, s0, s1, pp); break;
280 case Shader::OPCODE_DIST4: dist4(d.x, s0, s1, pp); break;
281 case Shader::OPCODE_SGE: step(d, s1, s0); break;
282 case Shader::OPCODE_SGN: sgn(d, s0); break;
Alexis Hetu0f448072016-03-18 10:56:08 -0400283 case Shader::OPCODE_ISGN: isgn(d, s0); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500284 case Shader::OPCODE_SINCOS: sincos(d, s0, pp); break;
285 case Shader::OPCODE_COS: cos(d, s0, pp); break;
286 case Shader::OPCODE_SIN: sin(d, s0, pp); break;
287 case Shader::OPCODE_TAN: tan(d, s0); break;
288 case Shader::OPCODE_ACOS: acos(d, s0); break;
289 case Shader::OPCODE_ASIN: asin(d, s0); break;
290 case Shader::OPCODE_ATAN: atan(d, s0); break;
291 case Shader::OPCODE_ATAN2: atan2(d, s0, s1); break;
292 case Shader::OPCODE_COSH: cosh(d, s0, pp); break;
293 case Shader::OPCODE_SINH: sinh(d, s0, pp); break;
294 case Shader::OPCODE_TANH: tanh(d, s0, pp); break;
295 case Shader::OPCODE_ACOSH: acosh(d, s0, pp); break;
296 case Shader::OPCODE_ASINH: asinh(d, s0, pp); break;
297 case Shader::OPCODE_ATANH: atanh(d, s0, pp); break;
298 case Shader::OPCODE_SLT: slt(d, s0, s1); break;
299 case Shader::OPCODE_SUB: sub(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400300 case Shader::OPCODE_ISUB: isub(d, s0, s1); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500301 case Shader::OPCODE_BREAK: BREAK(); break;
302 case Shader::OPCODE_BREAKC: BREAKC(s0, s1, control); break;
303 case Shader::OPCODE_BREAKP: BREAKP(src0); break;
304 case Shader::OPCODE_CONTINUE: CONTINUE(); break;
305 case Shader::OPCODE_TEST: TEST(); break;
Nicolas Capens6e8ec332018-11-06 11:56:21 -0500306 case Shader::OPCODE_SCALAR: SCALAR(); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500307 case Shader::OPCODE_CALL: CALL(dst.label, dst.callSite); break;
308 case Shader::OPCODE_CALLNZ: CALLNZ(dst.label, dst.callSite, src0); break;
309 case Shader::OPCODE_ELSE: ELSE(); break;
310 case Shader::OPCODE_ENDIF: ENDIF(); break;
311 case Shader::OPCODE_ENDLOOP: ENDLOOP(); break;
312 case Shader::OPCODE_ENDREP: ENDREP(); break;
313 case Shader::OPCODE_ENDWHILE: ENDWHILE(); break;
Alexis Hetu9aa83a92016-05-02 17:34:46 -0400314 case Shader::OPCODE_ENDSWITCH: ENDSWITCH(); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500315 case Shader::OPCODE_IF: IF(src0); break;
316 case Shader::OPCODE_IFC: IFC(s0, s1, control); break;
317 case Shader::OPCODE_LABEL: LABEL(dst.index); break;
318 case Shader::OPCODE_LOOP: LOOP(src1); break;
319 case Shader::OPCODE_REP: REP(src0); break;
320 case Shader::OPCODE_WHILE: WHILE(src0); break;
Alexis Hetu9aa83a92016-05-02 17:34:46 -0400321 case Shader::OPCODE_SWITCH: SWITCH(); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500322 case Shader::OPCODE_RET: RET(); break;
323 case Shader::OPCODE_LEAVE: LEAVE(); break;
324 case Shader::OPCODE_CMP: cmp(d, s0, s1, control); break;
325 case Shader::OPCODE_ICMP: icmp(d, s0, s1, control); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400326 case Shader::OPCODE_UCMP: ucmp(d, s0, s1, control); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500327 case Shader::OPCODE_SELECT: select(d, s0, s1, s2); break;
328 case Shader::OPCODE_EXTRACT: extract(d.x, s0, s1.x); break;
329 case Shader::OPCODE_INSERT: insert(d, s0, s1.x, s2.x); break;
330 case Shader::OPCODE_ALL: all(d.x, s0); break;
331 case Shader::OPCODE_ANY: any(d.x, s0); break;
Alexis Hetu24f454e2016-08-31 17:22:13 -0400332 case Shader::OPCODE_NOT: bitwise_not(d, s0); break;
333 case Shader::OPCODE_OR: bitwise_or(d, s0, s1); break;
334 case Shader::OPCODE_XOR: bitwise_xor(d, s0, s1); break;
335 case Shader::OPCODE_AND: bitwise_and(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400336 case Shader::OPCODE_EQ: equal(d, s0, s1); break;
337 case Shader::OPCODE_NE: notEqual(d, s0, s1); break;
Nicolas Capensa0b57832017-11-07 13:07:53 -0500338 case Shader::OPCODE_TEXLDL: TEXLOD(d, s0, src1, s0.w); break;
339 case Shader::OPCODE_TEXLOD: TEXLOD(d, s0, src1, s2.x); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500340 case Shader::OPCODE_TEX: TEX(d, s0, src1); break;
Meng-Lin Wu2337a192016-06-01 13:54:07 -0400341 case Shader::OPCODE_TEXOFFSET: TEXOFFSET(d, s0, src1, s2); break;
Nicolas Capensa0b57832017-11-07 13:07:53 -0500342 case Shader::OPCODE_TEXLODOFFSET: TEXLODOFFSET(d, s0, src1, s2, s3.x); break;
343 case Shader::OPCODE_TEXELFETCH: TEXELFETCH(d, s0, src1, s2.x); break;
344 case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCHOFFSET(d, s0, src1, s2, s3.x); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500345 case Shader::OPCODE_TEXGRAD: TEXGRAD(d, s0, src1, s2, s3); break;
Nicolas Capensa0b57832017-11-07 13:07:53 -0500346 case Shader::OPCODE_TEXGRADOFFSET: TEXGRADOFFSET(d, s0, src1, s2, s3, s4); break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500347 case Shader::OPCODE_TEXSIZE: TEXSIZE(d, s0.x, src1); break;
348 case Shader::OPCODE_END: break;
John Bauman89401822014-05-06 15:04:28 -0400349 default:
350 ASSERT(false);
351 }
352
John Bauman19bac1e2014-05-06 15:23:49 -0400353 if(dst.type != Shader::PARAMETER_VOID && dst.type != Shader::PARAMETER_LABEL && opcode != Shader::OPCODE_NOP)
John Bauman89401822014-05-06 15:04:28 -0400354 {
John Bauman19bac1e2014-05-06 15:23:49 -0400355 if(dst.saturate)
John Bauman89401822014-05-06 15:04:28 -0400356 {
John Bauman19bac1e2014-05-06 15:23:49 -0400357 if(dst.x) d.x = Max(d.x, Float4(0.0f));
358 if(dst.y) d.y = Max(d.y, Float4(0.0f));
359 if(dst.z) d.z = Max(d.z, Float4(0.0f));
360 if(dst.w) d.w = Max(d.w, Float4(0.0f));
John Bauman89401822014-05-06 15:04:28 -0400361
John Bauman19bac1e2014-05-06 15:23:49 -0400362 if(dst.x) d.x = Min(d.x, Float4(1.0f));
363 if(dst.y) d.y = Min(d.y, Float4(1.0f));
364 if(dst.z) d.z = Min(d.z, Float4(1.0f));
365 if(dst.w) d.w = Min(d.w, Float4(1.0f));
366 }
367
Nicolas Capensc6e8ab12014-05-06 23:31:07 -0400368 if(instruction->isPredicated())
John Bauman19bac1e2014-05-06 15:23:49 -0400369 {
370 Vector4f pDst; // FIXME: Rename
371
372 switch(dst.type)
John Bauman89401822014-05-06 15:04:28 -0400373 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500374 case Shader::PARAMETER_VOID: break;
John Bauman19bac1e2014-05-06 15:23:49 -0400375 case Shader::PARAMETER_TEMP:
376 if(dst.rel.type == Shader::PARAMETER_VOID)
377 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500378 if(dst.x) pDst.x = r[dst.index].x;
379 if(dst.y) pDst.y = r[dst.index].y;
380 if(dst.z) pDst.z = r[dst.index].z;
381 if(dst.w) pDst.w = r[dst.index].w;
John Bauman19bac1e2014-05-06 15:23:49 -0400382 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400383 else if(!dst.rel.dynamic)
384 {
385 Int a = dst.index + relativeAddress(dst.rel);
386
387 if(dst.x) pDst.x = r[a].x;
388 if(dst.y) pDst.y = r[a].y;
389 if(dst.z) pDst.z = r[a].z;
390 if(dst.w) pDst.w = r[a].w;
391 }
John Bauman19bac1e2014-05-06 15:23:49 -0400392 else
393 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400394 Int4 a = dst.index + dynamicAddress(dst.rel);
John Bauman19bac1e2014-05-06 15:23:49 -0400395
Nicolas Capens4b743732018-05-28 13:22:07 -0400396 if(dst.x) pDst.x = r[a].x;
397 if(dst.y) pDst.y = r[a].y;
398 if(dst.z) pDst.z = r[a].z;
399 if(dst.w) pDst.w = r[a].w;
John Bauman19bac1e2014-05-06 15:23:49 -0400400 }
401 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500402 case Shader::PARAMETER_ADDR: pDst = a0; break;
John Bauman19bac1e2014-05-06 15:23:49 -0400403 case Shader::PARAMETER_RASTOUT:
404 switch(dst.index)
John Bauman89401822014-05-06 15:04:28 -0400405 {
406 case 0:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500407 if(dst.x) pDst.x = o[Pos].x;
408 if(dst.y) pDst.y = o[Pos].y;
409 if(dst.z) pDst.z = o[Pos].z;
410 if(dst.w) pDst.w = o[Pos].w;
John Bauman89401822014-05-06 15:04:28 -0400411 break;
412 case 1:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500413 pDst.x = o[Fog].x;
John Bauman89401822014-05-06 15:04:28 -0400414 break;
415 case 2:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500416 pDst.x = o[Pts].y;
John Bauman89401822014-05-06 15:04:28 -0400417 break;
418 default:
419 ASSERT(false);
420 }
421 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400422 case Shader::PARAMETER_ATTROUT:
Nicolas Capens995ddea2016-05-17 11:48:56 -0400423 if(dst.x) pDst.x = o[C0 + dst.index].x;
424 if(dst.y) pDst.y = o[C0 + dst.index].y;
425 if(dst.z) pDst.z = o[C0 + dst.index].z;
426 if(dst.w) pDst.w = o[C0 + dst.index].w;
John Bauman89401822014-05-06 15:04:28 -0400427 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400428 case Shader::PARAMETER_TEXCRDOUT:
429 // case Shader::PARAMETER_OUTPUT:
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500430 if(shaderModel < 0x0300)
John Bauman89401822014-05-06 15:04:28 -0400431 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500432 if(dst.x) pDst.x = o[T0 + dst.index].x;
433 if(dst.y) pDst.y = o[T0 + dst.index].y;
434 if(dst.z) pDst.z = o[T0 + dst.index].z;
435 if(dst.w) pDst.w = o[T0 + dst.index].w;
John Bauman89401822014-05-06 15:04:28 -0400436 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400437 else if(dst.rel.type == Shader::PARAMETER_VOID) // Not relative
438 {
439 if(dst.x) pDst.x = o[dst.index].x;
440 if(dst.y) pDst.y = o[dst.index].y;
441 if(dst.z) pDst.z = o[dst.index].z;
442 if(dst.w) pDst.w = o[dst.index].w;
443 }
444 else if(!dst.rel.dynamic)
445 {
446 Int a = dst.index + relativeAddress(dst.rel);
447
448 if(dst.x) pDst.x = o[a].x;
449 if(dst.y) pDst.y = o[a].y;
450 if(dst.z) pDst.z = o[a].z;
451 if(dst.w) pDst.w = o[a].w;
452 }
John Bauman89401822014-05-06 15:04:28 -0400453 else
454 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400455 Int4 a = dst.index + dynamicAddress(dst.rel);
John Bauman19bac1e2014-05-06 15:23:49 -0400456
Nicolas Capens4b743732018-05-28 13:22:07 -0400457 if(dst.x) pDst.x = o[a].x;
458 if(dst.y) pDst.y = o[a].y;
459 if(dst.z) pDst.z = o[a].z;
460 if(dst.w) pDst.w = o[a].w;
John Bauman89401822014-05-06 15:04:28 -0400461 }
462 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500463 case Shader::PARAMETER_LABEL: break;
464 case Shader::PARAMETER_PREDICATE: pDst = p0; break;
465 case Shader::PARAMETER_INPUT: break;
John Bauman89401822014-05-06 15:04:28 -0400466 default:
467 ASSERT(false);
468 }
469
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500470 Int4 enable = enableMask(instruction);
John Bauman89401822014-05-06 15:04:28 -0400471
472 Int4 xEnable = enable;
473 Int4 yEnable = enable;
474 Int4 zEnable = enable;
475 Int4 wEnable = enable;
476
477 if(predicate)
478 {
John Bauman19bac1e2014-05-06 15:23:49 -0400479 unsigned char pSwizzle = instruction->predicateSwizzle;
John Bauman89401822014-05-06 15:04:28 -0400480
Nicolas Capens7551ac62016-01-20 17:11:53 -0500481 Float4 xPredicate = p0[(pSwizzle >> 0) & 0x03];
482 Float4 yPredicate = p0[(pSwizzle >> 2) & 0x03];
483 Float4 zPredicate = p0[(pSwizzle >> 4) & 0x03];
484 Float4 wPredicate = p0[(pSwizzle >> 6) & 0x03];
John Bauman89401822014-05-06 15:04:28 -0400485
John Bauman19bac1e2014-05-06 15:23:49 -0400486 if(!instruction->predicateNot)
John Bauman89401822014-05-06 15:04:28 -0400487 {
John Bauman19bac1e2014-05-06 15:23:49 -0400488 if(dst.x) xEnable = xEnable & As<Int4>(xPredicate);
489 if(dst.y) yEnable = yEnable & As<Int4>(yPredicate);
490 if(dst.z) zEnable = zEnable & As<Int4>(zPredicate);
491 if(dst.w) wEnable = wEnable & As<Int4>(wPredicate);
John Bauman89401822014-05-06 15:04:28 -0400492 }
493 else
494 {
John Bauman19bac1e2014-05-06 15:23:49 -0400495 if(dst.x) xEnable = xEnable & ~As<Int4>(xPredicate);
496 if(dst.y) yEnable = yEnable & ~As<Int4>(yPredicate);
497 if(dst.z) zEnable = zEnable & ~As<Int4>(zPredicate);
498 if(dst.w) wEnable = wEnable & ~As<Int4>(wPredicate);
John Bauman89401822014-05-06 15:04:28 -0400499 }
500 }
501
John Bauman19bac1e2014-05-06 15:23:49 -0400502 if(dst.x) d.x = As<Float4>(As<Int4>(d.x) & xEnable);
503 if(dst.y) d.y = As<Float4>(As<Int4>(d.y) & yEnable);
504 if(dst.z) d.z = As<Float4>(As<Int4>(d.z) & zEnable);
505 if(dst.w) d.w = As<Float4>(As<Int4>(d.w) & wEnable);
John Bauman89401822014-05-06 15:04:28 -0400506
John Bauman19bac1e2014-05-06 15:23:49 -0400507 if(dst.x) d.x = As<Float4>(As<Int4>(d.x) | (As<Int4>(pDst.x) & ~xEnable));
508 if(dst.y) d.y = As<Float4>(As<Int4>(d.y) | (As<Int4>(pDst.y) & ~yEnable));
509 if(dst.z) d.z = As<Float4>(As<Int4>(d.z) | (As<Int4>(pDst.z) & ~zEnable));
510 if(dst.w) d.w = As<Float4>(As<Int4>(d.w) | (As<Int4>(pDst.w) & ~wEnable));
John Bauman89401822014-05-06 15:04:28 -0400511 }
512
John Bauman19bac1e2014-05-06 15:23:49 -0400513 switch(dst.type)
John Bauman89401822014-05-06 15:04:28 -0400514 {
John Bauman19bac1e2014-05-06 15:23:49 -0400515 case Shader::PARAMETER_VOID:
John Bauman89401822014-05-06 15:04:28 -0400516 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400517 case Shader::PARAMETER_TEMP:
518 if(dst.rel.type == Shader::PARAMETER_VOID)
519 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500520 if(dst.x) r[dst.index].x = d.x;
521 if(dst.y) r[dst.index].y = d.y;
522 if(dst.z) r[dst.index].z = d.z;
523 if(dst.w) r[dst.index].w = d.w;
John Bauman19bac1e2014-05-06 15:23:49 -0400524 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400525 else if(!dst.rel.dynamic)
526 {
527 Int a = dst.index + relativeAddress(dst.rel);
528
529 if(dst.x) r[a].x = d.x;
530 if(dst.y) r[a].y = d.y;
531 if(dst.z) r[a].z = d.z;
532 if(dst.w) r[a].w = d.w;
533 }
John Bauman19bac1e2014-05-06 15:23:49 -0400534 else
535 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400536 Int4 a = dst.index + dynamicAddress(dst.rel);
John Bauman19bac1e2014-05-06 15:23:49 -0400537
Nicolas Capens4b743732018-05-28 13:22:07 -0400538 if(dst.x) r.scatter_x(a, d.x);
539 if(dst.y) r.scatter_y(a, d.y);
540 if(dst.z) r.scatter_z(a, d.z);
541 if(dst.w) r.scatter_w(a, d.w);
John Bauman19bac1e2014-05-06 15:23:49 -0400542 }
John Bauman89401822014-05-06 15:04:28 -0400543 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400544 case Shader::PARAMETER_ADDR:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500545 if(dst.x) a0.x = d.x;
546 if(dst.y) a0.y = d.y;
547 if(dst.z) a0.z = d.z;
548 if(dst.w) a0.w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400549 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400550 case Shader::PARAMETER_RASTOUT:
551 switch(dst.index)
John Bauman89401822014-05-06 15:04:28 -0400552 {
553 case 0:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500554 if(dst.x) o[Pos].x = d.x;
555 if(dst.y) o[Pos].y = d.y;
556 if(dst.z) o[Pos].z = d.z;
557 if(dst.w) o[Pos].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400558 break;
559 case 1:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500560 o[Fog].x = d.x;
John Bauman89401822014-05-06 15:04:28 -0400561 break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500562 case 2:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500563 o[Pts].y = d.x;
John Bauman89401822014-05-06 15:04:28 -0400564 break;
565 default: ASSERT(false);
566 }
567 break;
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500568 case Shader::PARAMETER_ATTROUT:
Nicolas Capens995ddea2016-05-17 11:48:56 -0400569 if(dst.x) o[C0 + dst.index].x = d.x;
570 if(dst.y) o[C0 + dst.index].y = d.y;
571 if(dst.z) o[C0 + dst.index].z = d.z;
572 if(dst.w) o[C0 + dst.index].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400573 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400574 case Shader::PARAMETER_TEXCRDOUT:
575 // case Shader::PARAMETER_OUTPUT:
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500576 if(shaderModel < 0x0300)
John Bauman89401822014-05-06 15:04:28 -0400577 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500578 if(dst.x) o[T0 + dst.index].x = d.x;
579 if(dst.y) o[T0 + dst.index].y = d.y;
580 if(dst.z) o[T0 + dst.index].z = d.z;
581 if(dst.w) o[T0 + dst.index].w = d.w;
John Bauman89401822014-05-06 15:04:28 -0400582 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400583 else if(dst.rel.type == Shader::PARAMETER_VOID) // Not relative
584 {
585 if(dst.x) o[dst.index].x = d.x;
586 if(dst.y) o[dst.index].y = d.y;
587 if(dst.z) o[dst.index].z = d.z;
588 if(dst.w) o[dst.index].w = d.w;
589 }
590 else if(!dst.rel.dynamic)
591 {
592 Int a = dst.index + relativeAddress(dst.rel);
593
594 if(dst.x) o[a].x = d.x;
595 if(dst.y) o[a].y = d.y;
596 if(dst.z) o[a].z = d.z;
597 if(dst.w) o[a].w = d.w;
598 }
John Bauman89401822014-05-06 15:04:28 -0400599 else
600 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400601 Int4 a = dst.index + dynamicAddress(dst.rel);
John Bauman19bac1e2014-05-06 15:23:49 -0400602
Nicolas Capens4b743732018-05-28 13:22:07 -0400603 if(dst.x) o.scatter_x(a, d.x);
604 if(dst.y) o.scatter_y(a, d.y);
605 if(dst.z) o.scatter_z(a, d.z);
606 if(dst.w) o.scatter_w(a, d.w);
John Bauman89401822014-05-06 15:04:28 -0400607 }
608 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500609 case Shader::PARAMETER_LABEL: break;
610 case Shader::PARAMETER_PREDICATE: p0 = d; break;
611 case Shader::PARAMETER_INPUT: break;
John Bauman89401822014-05-06 15:04:28 -0400612 default:
613 ASSERT(false);
614 }
615 }
616 }
617
John Bauman19bac1e2014-05-06 15:23:49 -0400618 if(currentLabel != -1)
John Bauman89401822014-05-06 15:04:28 -0400619 {
620 Nucleus::setInsertBlock(returnBlock);
621 }
622 }
623
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500624 void VertexProgram::passThrough()
John Bauman89401822014-05-06 15:04:28 -0400625 {
John Bauman19bac1e2014-05-06 15:23:49 -0400626 if(shader)
John Bauman89401822014-05-06 15:04:28 -0400627 {
Nicolas Capensec0936c2016-05-18 12:32:02 -0400628 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400629 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400630 unsigned char usage = shader->getOutput(i, 0).usage;
John Bauman89401822014-05-06 15:04:28 -0400631
632 switch(usage)
633 {
634 case 0xFF:
635 continue;
John Bauman19bac1e2014-05-06 15:23:49 -0400636 case Shader::USAGE_PSIZE:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500637 o[i].y = v[i].x;
John Bauman89401822014-05-06 15:04:28 -0400638 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400639 case Shader::USAGE_TEXCOORD:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500640 o[i].x = v[i].x;
641 o[i].y = v[i].y;
642 o[i].z = v[i].z;
643 o[i].w = v[i].w;
John Bauman89401822014-05-06 15:04:28 -0400644 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400645 case Shader::USAGE_POSITION:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500646 o[i].x = v[i].x;
647 o[i].y = v[i].y;
648 o[i].z = v[i].z;
649 o[i].w = v[i].w;
John Bauman89401822014-05-06 15:04:28 -0400650 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400651 case Shader::USAGE_COLOR:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500652 o[i].x = v[i].x;
653 o[i].y = v[i].y;
654 o[i].z = v[i].z;
655 o[i].w = v[i].w;
John Bauman89401822014-05-06 15:04:28 -0400656 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400657 case Shader::USAGE_FOG:
Nicolas Capens7551ac62016-01-20 17:11:53 -0500658 o[i].x = v[i].x;
John Bauman89401822014-05-06 15:04:28 -0400659 break;
660 default:
661 ASSERT(false);
662 }
663 }
664 }
665 else
666 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500667 o[Pos].x = v[PositionT].x;
668 o[Pos].y = v[PositionT].y;
669 o[Pos].z = v[PositionT].z;
670 o[Pos].w = v[PositionT].w;
John Bauman89401822014-05-06 15:04:28 -0400671
672 for(int i = 0; i < 2; i++)
673 {
Nicolas Capens995ddea2016-05-17 11:48:56 -0400674 o[C0 + i].x = v[Color0 + i].x;
675 o[C0 + i].y = v[Color0 + i].y;
676 o[C0 + i].z = v[Color0 + i].z;
677 o[C0 + i].w = v[Color0 + i].w;
John Bauman89401822014-05-06 15:04:28 -0400678 }
679
680 for(int i = 0; i < 8; i++)
681 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500682 o[T0 + i].x = v[TexCoord0 + i].x;
683 o[T0 + i].y = v[TexCoord0 + i].y;
684 o[T0 + i].z = v[TexCoord0 + i].z;
685 o[T0 + i].w = v[TexCoord0 + i].w;
John Bauman89401822014-05-06 15:04:28 -0400686 }
687
Nicolas Capens7551ac62016-01-20 17:11:53 -0500688 o[Pts].y = v[PointSize].x;
John Bauman89401822014-05-06 15:04:28 -0400689 }
690 }
691
Nicolas Capensc2534f42016-04-04 11:13:24 -0400692 Vector4f VertexProgram::fetchRegister(const Src &src, unsigned int offset)
John Bauman89401822014-05-06 15:04:28 -0400693 {
John Bauman19bac1e2014-05-06 15:23:49 -0400694 Vector4f reg;
Nicolas Capens5d961882016-01-01 23:18:14 -0500695 unsigned int i = src.index + offset;
John Bauman89401822014-05-06 15:04:28 -0400696
John Bauman89401822014-05-06 15:04:28 -0400697 switch(src.type)
698 {
John Bauman19bac1e2014-05-06 15:23:49 -0400699 case Shader::PARAMETER_TEMP:
700 if(src.rel.type == Shader::PARAMETER_VOID)
701 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500702 reg = r[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400703 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400704 else if(!src.rel.dynamic)
705 {
706 reg = r[i + relativeAddress(src.rel, src.bufferIndex)];
707 }
John Bauman19bac1e2014-05-06 15:23:49 -0400708 else
709 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400710 reg = r[i + dynamicAddress(src.rel)];
John Bauman19bac1e2014-05-06 15:23:49 -0400711 }
712 break;
713 case Shader::PARAMETER_CONST:
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500714 reg = readConstant(src, offset);
John Bauman19bac1e2014-05-06 15:23:49 -0400715 break;
716 case Shader::PARAMETER_INPUT:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400717 if(src.rel.type == Shader::PARAMETER_VOID)
John Bauman19bac1e2014-05-06 15:23:49 -0400718 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500719 reg = v[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400720 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400721 else if(!src.rel.dynamic)
722 {
723 reg = v[i + relativeAddress(src.rel, src.bufferIndex)];
724 }
John Bauman19bac1e2014-05-06 15:23:49 -0400725 else
726 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400727 reg = v[i + dynamicAddress(src.rel)];
John Bauman19bac1e2014-05-06 15:23:49 -0400728 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400729 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500730 case Shader::PARAMETER_VOID: return r[0]; // Dummy
John Bauman19bac1e2014-05-06 15:23:49 -0400731 case Shader::PARAMETER_FLOAT4LITERAL:
732 reg.x = Float4(src.value[0]);
733 reg.y = Float4(src.value[1]);
734 reg.z = Float4(src.value[2]);
735 reg.w = Float4(src.value[3]);
736 break;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500737 case Shader::PARAMETER_ADDR: reg = a0; break;
738 case Shader::PARAMETER_CONSTBOOL: return r[0]; // Dummy
739 case Shader::PARAMETER_CONSTINT: return r[0]; // Dummy
740 case Shader::PARAMETER_LOOP: return r[0]; // Dummy
741 case Shader::PARAMETER_PREDICATE: return r[0]; // Dummy
John Bauman19bac1e2014-05-06 15:23:49 -0400742 case Shader::PARAMETER_SAMPLER:
743 if(src.rel.type == Shader::PARAMETER_VOID)
744 {
745 reg.x = As<Float4>(Int4(i));
746 }
747 else if(src.rel.type == Shader::PARAMETER_TEMP)
748 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500749 reg.x = As<Float4>(Int4(i) + As<Int4>(r[src.rel.index].x));
John Bauman19bac1e2014-05-06 15:23:49 -0400750 }
751 return reg;
752 case Shader::PARAMETER_OUTPUT:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400753 if(src.rel.type == Shader::PARAMETER_VOID)
John Bauman19bac1e2014-05-06 15:23:49 -0400754 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500755 reg = o[i];
John Bauman19bac1e2014-05-06 15:23:49 -0400756 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400757 else if(!src.rel.dynamic)
758 {
759 reg = o[i + relativeAddress(src.rel, src.bufferIndex)];
760 }
John Bauman19bac1e2014-05-06 15:23:49 -0400761 else
762 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400763 reg = o[i + dynamicAddress(src.rel)];
John Bauman19bac1e2014-05-06 15:23:49 -0400764 }
765 break;
Alexis Hetudd8df682015-06-05 17:08:39 -0400766 case Shader::PARAMETER_MISCTYPE:
Alexis Hetu877ddfc2017-07-25 17:48:00 -0400767 if(src.index == Shader::InstanceIDIndex)
768 {
769 reg.x = As<Float>(instanceID);
770 }
771 else if(src.index == Shader::VertexIDIndex)
772 {
773 reg.x = As<Float4>(vertexID);
774 }
775 else ASSERT(false);
Alexis Hetudd8df682015-06-05 17:08:39 -0400776 return reg;
John Bauman89401822014-05-06 15:04:28 -0400777 default:
778 ASSERT(false);
779 }
780
John Bauman66b8ab22014-05-06 15:57:45 -0400781 const Float4 &x = reg[(src.swizzle >> 0) & 0x3];
782 const Float4 &y = reg[(src.swizzle >> 2) & 0x3];
783 const Float4 &z = reg[(src.swizzle >> 4) & 0x3];
784 const Float4 &w = reg[(src.swizzle >> 6) & 0x3];
John Bauman89401822014-05-06 15:04:28 -0400785
John Bauman66b8ab22014-05-06 15:57:45 -0400786 Vector4f mod;
John Bauman89401822014-05-06 15:04:28 -0400787
788 switch(src.modifier)
789 {
John Bauman19bac1e2014-05-06 15:23:49 -0400790 case Shader::MODIFIER_NONE:
John Bauman66b8ab22014-05-06 15:57:45 -0400791 mod.x = x;
792 mod.y = y;
793 mod.z = z;
794 mod.w = w;
John Bauman89401822014-05-06 15:04:28 -0400795 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400796 case Shader::MODIFIER_NEGATE:
John Bauman66b8ab22014-05-06 15:57:45 -0400797 mod.x = -x;
798 mod.y = -y;
799 mod.z = -z;
800 mod.w = -w;
John Bauman89401822014-05-06 15:04:28 -0400801 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400802 case Shader::MODIFIER_ABS:
John Bauman66b8ab22014-05-06 15:57:45 -0400803 mod.x = Abs(x);
804 mod.y = Abs(y);
805 mod.z = Abs(z);
806 mod.w = Abs(w);
John Bauman89401822014-05-06 15:04:28 -0400807 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400808 case Shader::MODIFIER_ABS_NEGATE:
John Bauman66b8ab22014-05-06 15:57:45 -0400809 mod.x = -Abs(x);
810 mod.y = -Abs(y);
811 mod.z = -Abs(z);
812 mod.w = -Abs(w);
John Bauman89401822014-05-06 15:04:28 -0400813 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400814 case Shader::MODIFIER_NOT:
John Bauman66b8ab22014-05-06 15:57:45 -0400815 mod.x = As<Float4>(As<Int4>(x) ^ Int4(0xFFFFFFFF));
816 mod.y = As<Float4>(As<Int4>(y) ^ Int4(0xFFFFFFFF));
817 mod.z = As<Float4>(As<Int4>(z) ^ Int4(0xFFFFFFFF));
818 mod.w = As<Float4>(As<Int4>(w) ^ Int4(0xFFFFFFFF));
John Bauman89401822014-05-06 15:04:28 -0400819 break;
820 default:
821 ASSERT(false);
822 }
823
824 return mod;
825 }
826
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400827 RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index)
828 {
829 if(bufferIndex == -1)
830 {
831 return data + OFFSET(DrawData, vs.c[index]);
832 }
833 else
834 {
835 return *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.u[bufferIndex])) + index;
836 }
837 }
838
Nicolas Capens4b743732018-05-28 13:22:07 -0400839 RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index, Int &offset)
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400840 {
841 return uniformAddress(bufferIndex, index) + offset * sizeof(float4);
842 }
843
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500844 Vector4f VertexProgram::readConstant(const Src &src, unsigned int offset)
John Bauman89401822014-05-06 15:04:28 -0400845 {
John Bauman19bac1e2014-05-06 15:23:49 -0400846 Vector4f c;
Nicolas Capens5d961882016-01-01 23:18:14 -0500847 unsigned int i = src.index + offset;
John Bauman19bac1e2014-05-06 15:23:49 -0400848
849 if(src.rel.type == Shader::PARAMETER_VOID) // Not relative
850 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400851 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i));
John Bauman19bac1e2014-05-06 15:23:49 -0400852
853 c.x = c.x.xxxx;
854 c.y = c.y.yyyy;
855 c.z = c.z.zzzz;
856 c.w = c.w.wwww;
857
Nicolas Capenseafdb222015-05-15 15:24:08 -0400858 if(shader->containsDefineInstruction()) // Constant may be known at compile time
John Bauman19bac1e2014-05-06 15:23:49 -0400859 {
Alexis Hetu903e0252014-11-25 14:25:32 -0500860 for(size_t j = 0; j < shader->getLength(); j++)
John Bauman19bac1e2014-05-06 15:23:49 -0400861 {
862 const Shader::Instruction &instruction = *shader->getInstruction(j);
863
864 if(instruction.opcode == Shader::OPCODE_DEF)
865 {
866 if(instruction.dst.index == i)
867 {
868 c.x = Float4(instruction.src[0].value[0]);
869 c.y = Float4(instruction.src[0].value[1]);
870 c.z = Float4(instruction.src[0].value[2]);
871 c.w = Float4(instruction.src[0].value[3]);
872
873 break;
874 }
875 }
876 }
877 }
878 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400879 else if(!src.rel.dynamic || src.rel.type == Shader::PARAMETER_LOOP)
John Bauman19bac1e2014-05-06 15:23:49 -0400880 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400881 Int a = relativeAddress(src.rel, src.bufferIndex);
John Bauman19bac1e2014-05-06 15:23:49 -0400882
Nicolas Capens4b743732018-05-28 13:22:07 -0400883 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, a));
John Bauman19bac1e2014-05-06 15:23:49 -0400884
885 c.x = c.x.xxxx;
886 c.y = c.y.yyyy;
887 c.z = c.z.zzzz;
888 c.w = c.w.wwww;
889 }
890 else
891 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400892 int component = src.rel.swizzle & 0x03;
893 Float4 a;
894
895 switch(src.rel.type)
John Bauman19bac1e2014-05-06 15:23:49 -0400896 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400897 case Shader::PARAMETER_ADDR: a = a0[component]; break;
898 case Shader::PARAMETER_TEMP: a = r[src.rel.index][component]; break;
899 case Shader::PARAMETER_INPUT: a = v[src.rel.index][component]; break;
900 case Shader::PARAMETER_OUTPUT: a = o[src.rel.index][component]; break;
901 case Shader::PARAMETER_CONST: a = *Pointer<Float>(uniformAddress(src.bufferIndex, src.rel.index) + component * sizeof(float)); break;
902 case Shader::PARAMETER_MISCTYPE:
903 switch(src.rel.index)
John Bauman19bac1e2014-05-06 15:23:49 -0400904 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400905 case Shader::InstanceIDIndex: a = As<Float4>(Int4(instanceID)); break;
906 case Shader::VertexIDIndex: a = As<Float4>(vertexID); break;
John Bauman19bac1e2014-05-06 15:23:49 -0400907 default: ASSERT(false);
908 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400909 break;
910 default: ASSERT(false);
John Bauman19bac1e2014-05-06 15:23:49 -0400911 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400912
913 Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
914
915 index = Min(As<UInt4>(index), UInt4(VERTEX_UNIFORM_VECTORS)); // Clamp to constant register range, c[VERTEX_UNIFORM_VECTORS] = {0, 0, 0, 0}
916
917 Int index0 = Extract(index, 0);
918 Int index1 = Extract(index, 1);
919 Int index2 = Extract(index, 2);
920 Int index3 = Extract(index, 3);
921
922 c.x = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index0), 16);
923 c.y = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index1), 16);
924 c.z = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index2), 16);
925 c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index3), 16);
926
927 transpose4x4(c.x, c.y, c.z, c.w);
John Bauman19bac1e2014-05-06 15:23:49 -0400928 }
929
930 return c;
931 }
932
Nicolas Capens4b743732018-05-28 13:22:07 -0400933 Int VertexProgram::relativeAddress(const Shader::Relative &rel, int bufferIndex)
John Bauman19bac1e2014-05-06 15:23:49 -0400934 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400935 ASSERT(!rel.dynamic);
John Bauman19bac1e2014-05-06 15:23:49 -0400936
Nicolas Capens4b743732018-05-28 13:22:07 -0400937 if(rel.type == Shader::PARAMETER_TEMP)
John Bauman19bac1e2014-05-06 15:23:49 -0400938 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400939 return As<Int>(Extract(r[rel.index].x, 0)) * rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400940 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400941 else if(rel.type == Shader::PARAMETER_INPUT)
John Bauman19bac1e2014-05-06 15:23:49 -0400942 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400943 return As<Int>(Extract(v[rel.index].x, 0)) * rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400944 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400945 else if(rel.type == Shader::PARAMETER_OUTPUT)
John Bauman19bac1e2014-05-06 15:23:49 -0400946 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400947 return As<Int>(Extract(o[rel.index].x, 0)) * rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400948 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400949 else if(rel.type == Shader::PARAMETER_CONST)
John Bauman19bac1e2014-05-06 15:23:49 -0400950 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400951 return *Pointer<Int>(uniformAddress(bufferIndex, rel.index)) * rel.scale;
John Bauman19bac1e2014-05-06 15:23:49 -0400952 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400953 else if(rel.type == Shader::PARAMETER_LOOP)
Nicolas Capens907700d2016-01-20 17:09:28 -0500954 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500955 return aL[loopDepth];
Nicolas Capens907700d2016-01-20 17:09:28 -0500956 }
John Bauman19bac1e2014-05-06 15:23:49 -0400957 else ASSERT(false);
958
959 return 0;
960 }
961
Nicolas Capens4b743732018-05-28 13:22:07 -0400962 Int4 VertexProgram::dynamicAddress(const Shader::Relative &rel)
963 {
964 int component = rel.swizzle & 0x03;
965 Float4 a;
966
967 switch(rel.type)
968 {
969 case Shader::PARAMETER_ADDR: a = a0[component]; break;
970 case Shader::PARAMETER_TEMP: a = r[rel.index][component]; break;
971 case Shader::PARAMETER_INPUT: a = v[rel.index][component]; break;
972 case Shader::PARAMETER_OUTPUT: a = o[rel.index][component]; break;
973 case Shader::PARAMETER_MISCTYPE:
974 switch(rel.index)
975 {
976 case Shader::InstanceIDIndex: a = As<Float>(instanceID); break;
977 case Shader::VertexIDIndex: a = As<Float4>(vertexID); break;
978 default: ASSERT(false);
979 }
980 break;
981 default: ASSERT(false);
982 }
983
984 return As<Int4>(a) * Int4(rel.scale);
985 }
986
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500987 Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
John Bauman19bac1e2014-05-06 15:23:49 -0400988 {
Nicolas Capens6e8ec332018-11-06 11:56:21 -0500989 if(scalar)
990 {
991 return Int4(0xFFFFFFFF);
992 }
993
Alexis Hetu48d47a42019-01-10 14:04:26 -0500994 Int4 enable = instruction->analysisBranch ? Int4(enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))]) : Int4(0xFFFFFFFF);
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500995
Nicolas Capens8a587712018-10-20 14:17:49 -0400996 if(shader->containsBreakInstruction() && instruction->analysisBreak)
John Bauman19bac1e2014-05-06 15:23:49 -0400997 {
Nicolas Capens8a587712018-10-20 14:17:49 -0400998 enable &= enableBreak;
999 }
John Bauman19bac1e2014-05-06 15:23:49 -04001000
Nicolas Capens8a587712018-10-20 14:17:49 -04001001 if(shader->containsContinueInstruction() && instruction->analysisContinue)
1002 {
1003 enable &= enableContinue;
1004 }
John Bauman19bac1e2014-05-06 15:23:49 -04001005
Nicolas Capens8a587712018-10-20 14:17:49 -04001006 if(shader->containsLeaveInstruction() && instruction->analysisLeave)
1007 {
1008 enable &= enableLeave;
John Bauman19bac1e2014-05-06 15:23:49 -04001009 }
1010
1011 return enable;
1012 }
1013
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001014 void VertexProgram::M3X2(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman19bac1e2014-05-06 15:23:49 -04001015 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001016 Vector4f row0 = fetchRegister(src1, 0);
1017 Vector4f row1 = fetchRegister(src1, 1);
John Bauman89401822014-05-06 15:04:28 -04001018
1019 dst.x = dot3(src0, row0);
1020 dst.y = dot3(src0, row1);
1021 }
1022
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001023 void VertexProgram::M3X3(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -04001024 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001025 Vector4f row0 = fetchRegister(src1, 0);
1026 Vector4f row1 = fetchRegister(src1, 1);
1027 Vector4f row2 = fetchRegister(src1, 2);
John Bauman89401822014-05-06 15:04:28 -04001028
1029 dst.x = dot3(src0, row0);
1030 dst.y = dot3(src0, row1);
1031 dst.z = dot3(src0, row2);
1032 }
1033
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001034 void VertexProgram::M3X4(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -04001035 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001036 Vector4f row0 = fetchRegister(src1, 0);
1037 Vector4f row1 = fetchRegister(src1, 1);
1038 Vector4f row2 = fetchRegister(src1, 2);
1039 Vector4f row3 = fetchRegister(src1, 3);
John Bauman89401822014-05-06 15:04:28 -04001040
1041 dst.x = dot3(src0, row0);
1042 dst.y = dot3(src0, row1);
1043 dst.z = dot3(src0, row2);
1044 dst.w = dot3(src0, row3);
1045 }
1046
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001047 void VertexProgram::M4X3(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -04001048 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001049 Vector4f row0 = fetchRegister(src1, 0);
1050 Vector4f row1 = fetchRegister(src1, 1);
1051 Vector4f row2 = fetchRegister(src1, 2);
John Bauman89401822014-05-06 15:04:28 -04001052
1053 dst.x = dot4(src0, row0);
1054 dst.y = dot4(src0, row1);
1055 dst.z = dot4(src0, row2);
1056 }
1057
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001058 void VertexProgram::M4X4(Vector4f &dst, Vector4f &src0, Src &src1)
John Bauman89401822014-05-06 15:04:28 -04001059 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001060 Vector4f row0 = fetchRegister(src1, 0);
1061 Vector4f row1 = fetchRegister(src1, 1);
1062 Vector4f row2 = fetchRegister(src1, 2);
1063 Vector4f row3 = fetchRegister(src1, 3);
John Bauman89401822014-05-06 15:04:28 -04001064
1065 dst.x = dot4(src0, row0);
1066 dst.y = dot4(src0, row1);
1067 dst.z = dot4(src0, row2);
1068 dst.w = dot4(src0, row3);
1069 }
1070
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001071 void VertexProgram::BREAK()
John Bauman89401822014-05-06 15:04:28 -04001072 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001073 enableBreak = enableBreak & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
John Bauman89401822014-05-06 15:04:28 -04001074 }
1075
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001076 void VertexProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
John Bauman89401822014-05-06 15:04:28 -04001077 {
1078 Int4 condition;
1079
1080 switch(control)
1081 {
Nicolas Capensac6d5052018-01-05 15:34:00 -05001082 case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
1083 case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x); break;
1084 case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
1085 case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x); break;
1086 case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
1087 case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x); break;
John Bauman89401822014-05-06 15:04:28 -04001088 default:
1089 ASSERT(false);
1090 }
1091
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001092 BREAK(condition);
John Bauman89401822014-05-06 15:04:28 -04001093 }
1094
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001095 void VertexProgram::BREAKP(const Src &predicateRegister) // FIXME: Factor out parts common with BREAKC
John Bauman89401822014-05-06 15:04:28 -04001096 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001097 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001098
John Bauman19bac1e2014-05-06 15:23:49 -04001099 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001100 {
1101 condition = ~condition;
1102 }
1103
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001104 BREAK(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001105 }
1106
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001107 void VertexProgram::BREAK(Int4 &condition)
John Bauman19bac1e2014-05-06 15:23:49 -04001108 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001109 condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
John Bauman89401822014-05-06 15:04:28 -04001110
Nicolas Capens7551ac62016-01-20 17:11:53 -05001111 enableBreak = enableBreak & ~condition;
John Bauman89401822014-05-06 15:04:28 -04001112 }
1113
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001114 void VertexProgram::CONTINUE()
John Bauman19bac1e2014-05-06 15:23:49 -04001115 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001116 enableContinue = enableContinue & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
John Bauman19bac1e2014-05-06 15:23:49 -04001117 }
1118
1119 void VertexProgram::TEST()
1120 {
Nicolas Capens2f490f02018-11-01 16:53:36 -04001121 enableContinue = restoreContinue.back();
1122 restoreContinue.pop_back();
John Bauman19bac1e2014-05-06 15:23:49 -04001123 }
1124
Nicolas Capens6e8ec332018-11-06 11:56:21 -05001125 void VertexProgram::SCALAR()
1126 {
1127 scalar = true;
1128 }
1129
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001130 void VertexProgram::CALL(int labelIndex, int callSiteIndex)
John Bauman89401822014-05-06 15:04:28 -04001131 {
1132 if(!labelBlock[labelIndex])
1133 {
1134 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1135 }
1136
John Bauman19bac1e2014-05-06 15:23:49 -04001137 if(callRetBlock[labelIndex].size() > 1)
1138 {
Nicolas Capens0f34a982019-02-11 16:02:23 -05001139 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001140 }
John Bauman89401822014-05-06 15:04:28 -04001141
Nicolas Capens7551ac62016-01-20 17:11:53 -05001142 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001143
1144 Nucleus::createBr(labelBlock[labelIndex]);
John Bauman19bac1e2014-05-06 15:23:49 -04001145 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1146
Nicolas Capens7551ac62016-01-20 17:11:53 -05001147 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001148 }
1149
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001150 void VertexProgram::CALLNZ(int labelIndex, int callSiteIndex, const Src &src)
John Bauman89401822014-05-06 15:04:28 -04001151 {
John Bauman19bac1e2014-05-06 15:23:49 -04001152 if(src.type == Shader::PARAMETER_CONSTBOOL)
John Bauman89401822014-05-06 15:04:28 -04001153 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001154 CALLNZb(labelIndex, callSiteIndex, src);
John Bauman89401822014-05-06 15:04:28 -04001155 }
John Bauman19bac1e2014-05-06 15:23:49 -04001156 else if(src.type == Shader::PARAMETER_PREDICATE)
John Bauman89401822014-05-06 15:04:28 -04001157 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001158 CALLNZp(labelIndex, callSiteIndex, src);
John Bauman89401822014-05-06 15:04:28 -04001159 }
1160 else ASSERT(false);
1161 }
1162
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001163 void VertexProgram::CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister)
John Bauman89401822014-05-06 15:04:28 -04001164 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001165 Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0)); // FIXME
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001166
John Bauman19bac1e2014-05-06 15:23:49 -04001167 if(boolRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001168 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001169 condition = !condition;
John Bauman89401822014-05-06 15:04:28 -04001170 }
1171
1172 if(!labelBlock[labelIndex])
1173 {
1174 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1175 }
1176
John Bauman19bac1e2014-05-06 15:23:49 -04001177 if(callRetBlock[labelIndex].size() > 1)
1178 {
Nicolas Capens0f34a982019-02-11 16:02:23 -05001179 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001180 }
John Bauman89401822014-05-06 15:04:28 -04001181
Nicolas Capens7551ac62016-01-20 17:11:53 -05001182 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001183
John Bauman19bac1e2014-05-06 15:23:49 -04001184 branch(condition, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
1185 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1186
Nicolas Capens7551ac62016-01-20 17:11:53 -05001187 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001188 }
1189
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001190 void VertexProgram::CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister)
John Bauman89401822014-05-06 15:04:28 -04001191 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001192 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001193
John Bauman19bac1e2014-05-06 15:23:49 -04001194 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001195 {
1196 condition = ~condition;
1197 }
1198
Alexis Hetu48d47a42019-01-10 14:04:26 -05001199 condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
John Bauman89401822014-05-06 15:04:28 -04001200
1201 if(!labelBlock[labelIndex])
1202 {
1203 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1204 }
1205
John Bauman19bac1e2014-05-06 15:23:49 -04001206 if(callRetBlock[labelIndex].size() > 1)
1207 {
Nicolas Capens0f34a982019-02-11 16:02:23 -05001208 callStack[stackIndex++] = UInt(callSiteIndex);
John Bauman19bac1e2014-05-06 15:23:49 -04001209 }
John Bauman89401822014-05-06 15:04:28 -04001210
Nicolas Capens7551ac62016-01-20 17:11:53 -05001211 enableIndex++;
Alexis Hetu48d47a42019-01-10 14:04:26 -05001212 enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
Nicolas Capens7551ac62016-01-20 17:11:53 -05001213 Int4 restoreLeave = enableLeave;
John Bauman89401822014-05-06 15:04:28 -04001214
John Bauman19bac1e2014-05-06 15:23:49 -04001215 Bool notAllFalse = SignMask(condition) != 0;
1216 branch(notAllFalse, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
1217 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
John Bauman89401822014-05-06 15:04:28 -04001218
Nicolas Capens7551ac62016-01-20 17:11:53 -05001219 enableIndex--;
1220 enableLeave = restoreLeave;
John Bauman89401822014-05-06 15:04:28 -04001221 }
1222
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001223 void VertexProgram::ELSE()
John Bauman89401822014-05-06 15:04:28 -04001224 {
1225 ifDepth--;
1226
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001227 BasicBlock *falseBlock = ifFalseBlock[ifDepth];
1228 BasicBlock *endBlock = Nucleus::createBasicBlock();
John Bauman89401822014-05-06 15:04:28 -04001229
1230 if(isConditionalIf[ifDepth])
1231 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001232 Int4 condition = ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] & enableStack[Min(enableIndex - 1, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
John Bauman19bac1e2014-05-06 15:23:49 -04001233 Bool notAllFalse = SignMask(condition) != 0;
John Bauman89401822014-05-06 15:04:28 -04001234
1235 branch(notAllFalse, falseBlock, endBlock);
1236
Alexis Hetu48d47a42019-01-10 14:04:26 -05001237 enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] & enableStack[Min(enableIndex - 1, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
John Bauman89401822014-05-06 15:04:28 -04001238 }
1239 else
1240 {
1241 Nucleus::createBr(endBlock);
1242 Nucleus::setInsertBlock(falseBlock);
1243 }
1244
1245 ifFalseBlock[ifDepth] = endBlock;
1246
1247 ifDepth++;
1248 }
1249
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001250 void VertexProgram::ENDIF()
John Bauman89401822014-05-06 15:04:28 -04001251 {
1252 ifDepth--;
1253
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001254 BasicBlock *endBlock = ifFalseBlock[ifDepth];
John Bauman89401822014-05-06 15:04:28 -04001255
1256 Nucleus::createBr(endBlock);
1257 Nucleus::setInsertBlock(endBlock);
1258
1259 if(isConditionalIf[ifDepth])
1260 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001261 enableIndex--;
John Bauman89401822014-05-06 15:04:28 -04001262 }
1263 }
1264
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001265 void VertexProgram::ENDLOOP()
John Bauman89401822014-05-06 15:04:28 -04001266 {
1267 loopRepDepth--;
1268
Nicolas Capens7551ac62016-01-20 17:11:53 -05001269 aL[loopDepth] = aL[loopDepth] + increment[loopDepth]; // FIXME: +=
John Bauman89401822014-05-06 15:04:28 -04001270
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001271 BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1272 BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
John Bauman89401822014-05-06 15:04:28 -04001273
1274 Nucleus::createBr(testBlock);
1275 Nucleus::setInsertBlock(endBlock);
1276
Nicolas Capens7551ac62016-01-20 17:11:53 -05001277 loopDepth--;
1278 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
John Bauman89401822014-05-06 15:04:28 -04001279 }
1280
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001281 void VertexProgram::ENDREP()
John Bauman19bac1e2014-05-06 15:23:49 -04001282 {
1283 loopRepDepth--;
1284
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001285 BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1286 BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
John Bauman19bac1e2014-05-06 15:23:49 -04001287
1288 Nucleus::createBr(testBlock);
1289 Nucleus::setInsertBlock(endBlock);
1290
Nicolas Capens7551ac62016-01-20 17:11:53 -05001291 loopDepth--;
1292 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
John Bauman19bac1e2014-05-06 15:23:49 -04001293 }
1294
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001295 void VertexProgram::ENDWHILE()
John Bauman19bac1e2014-05-06 15:23:49 -04001296 {
1297 loopRepDepth--;
1298
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001299 BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1300 BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
John Bauman19bac1e2014-05-06 15:23:49 -04001301
1302 Nucleus::createBr(testBlock);
1303 Nucleus::setInsertBlock(endBlock);
1304
Nicolas Capens7551ac62016-01-20 17:11:53 -05001305 enableIndex--;
Nicolas Capens6e8ec332018-11-06 11:56:21 -05001306 scalar = false;
John Bauman19bac1e2014-05-06 15:23:49 -04001307 }
1308
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001309 void VertexProgram::ENDSWITCH()
1310 {
1311 loopRepDepth--;
1312
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001313 BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
Nicolas Capensec0936c2016-05-18 12:32:02 -04001314
Nicolas Capensac6d5052018-01-05 15:34:00 -05001315 Nucleus::createBr(endBlock);
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001316 Nucleus::setInsertBlock(endBlock);
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001317 }
1318
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001319 void VertexProgram::IF(const Src &src)
John Bauman89401822014-05-06 15:04:28 -04001320 {
John Bauman19bac1e2014-05-06 15:23:49 -04001321 if(src.type == Shader::PARAMETER_CONSTBOOL)
John Bauman89401822014-05-06 15:04:28 -04001322 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001323 IFb(src);
John Bauman89401822014-05-06 15:04:28 -04001324 }
John Bauman19bac1e2014-05-06 15:23:49 -04001325 else if(src.type == Shader::PARAMETER_PREDICATE)
John Bauman89401822014-05-06 15:04:28 -04001326 {
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001327 IFp(src);
John Bauman89401822014-05-06 15:04:28 -04001328 }
John Bauman19bac1e2014-05-06 15:23:49 -04001329 else
1330 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001331 Int4 condition = As<Int4>(fetchRegister(src).x);
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001332 IF(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001333 }
John Bauman89401822014-05-06 15:04:28 -04001334 }
1335
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001336 void VertexProgram::IFb(const Src &boolRegister)
John Bauman89401822014-05-06 15:04:28 -04001337 {
1338 ASSERT(ifDepth < 24 + 4);
1339
Nicolas Capens7551ac62016-01-20 17:11:53 -05001340 Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0)); // FIXME
John Bauman89401822014-05-06 15:04:28 -04001341
John Bauman19bac1e2014-05-06 15:23:49 -04001342 if(boolRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001343 {
John Bauman19bac1e2014-05-06 15:23:49 -04001344 condition = !condition;
John Bauman89401822014-05-06 15:04:28 -04001345 }
1346
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001347 BasicBlock *trueBlock = Nucleus::createBasicBlock();
1348 BasicBlock *falseBlock = Nucleus::createBasicBlock();
John Bauman89401822014-05-06 15:04:28 -04001349
1350 branch(condition, trueBlock, falseBlock);
1351
1352 isConditionalIf[ifDepth] = false;
1353 ifFalseBlock[ifDepth] = falseBlock;
1354
1355 ifDepth++;
1356 }
1357
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001358 void VertexProgram::IFp(const Src &predicateRegister)
John Bauman89401822014-05-06 15:04:28 -04001359 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001360 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
John Bauman89401822014-05-06 15:04:28 -04001361
John Bauman19bac1e2014-05-06 15:23:49 -04001362 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
John Bauman89401822014-05-06 15:04:28 -04001363 {
1364 condition = ~condition;
1365 }
1366
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001367 IF(condition);
John Bauman89401822014-05-06 15:04:28 -04001368 }
1369
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001370 void VertexProgram::IFC(Vector4f &src0, Vector4f &src1, Control control)
John Bauman89401822014-05-06 15:04:28 -04001371 {
1372 Int4 condition;
1373
1374 switch(control)
1375 {
Nicolas Capensac6d5052018-01-05 15:34:00 -05001376 case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
1377 case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x); break;
1378 case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
1379 case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x); break;
1380 case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
1381 case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x); break;
John Bauman89401822014-05-06 15:04:28 -04001382 default:
1383 ASSERT(false);
1384 }
1385
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001386 IF(condition);
John Bauman19bac1e2014-05-06 15:23:49 -04001387 }
1388
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001389 void VertexProgram::IF(Int4 &condition)
John Bauman19bac1e2014-05-06 15:23:49 -04001390 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001391 condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
John Bauman89401822014-05-06 15:04:28 -04001392
Nicolas Capens7551ac62016-01-20 17:11:53 -05001393 enableIndex++;
Alexis Hetu48d47a42019-01-10 14:04:26 -05001394 enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
John Bauman89401822014-05-06 15:04:28 -04001395
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001396 BasicBlock *trueBlock = Nucleus::createBasicBlock();
1397 BasicBlock *falseBlock = Nucleus::createBasicBlock();
John Bauman89401822014-05-06 15:04:28 -04001398
John Bauman19bac1e2014-05-06 15:23:49 -04001399 Bool notAllFalse = SignMask(condition) != 0;
John Bauman89401822014-05-06 15:04:28 -04001400
1401 branch(notAllFalse, trueBlock, falseBlock);
1402
1403 isConditionalIf[ifDepth] = true;
1404 ifFalseBlock[ifDepth] = falseBlock;
1405
1406 ifDepth++;
John Bauman89401822014-05-06 15:04:28 -04001407 }
1408
1409 void VertexProgram::LABEL(int labelIndex)
1410 {
John Bauman19bac1e2014-05-06 15:23:49 -04001411 if(!labelBlock[labelIndex])
1412 {
1413 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1414 }
1415
John Bauman89401822014-05-06 15:04:28 -04001416 Nucleus::setInsertBlock(labelBlock[labelIndex]);
John Bauman19bac1e2014-05-06 15:23:49 -04001417 currentLabel = labelIndex;
John Bauman89401822014-05-06 15:04:28 -04001418 }
1419
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001420 void VertexProgram::LOOP(const Src &integerRegister)
John Bauman89401822014-05-06 15:04:28 -04001421 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001422 loopDepth++;
John Bauman89401822014-05-06 15:04:28 -04001423
Nicolas Capens7551ac62016-01-20 17:11:53 -05001424 iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
1425 aL[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][1]));
1426 increment[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][2]));
John Bauman89401822014-05-06 15:04:28 -04001427
1428 // FIXME: Compiles to two instructions?
Nicolas Capens7551ac62016-01-20 17:11:53 -05001429 If(increment[loopDepth] == 0)
John Bauman89401822014-05-06 15:04:28 -04001430 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001431 increment[loopDepth] = 1;
John Bauman89401822014-05-06 15:04:28 -04001432 }
1433
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001434 BasicBlock *loopBlock = Nucleus::createBasicBlock();
1435 BasicBlock *testBlock = Nucleus::createBasicBlock();
1436 BasicBlock *endBlock = Nucleus::createBasicBlock();
John Bauman89401822014-05-06 15:04:28 -04001437
1438 loopRepTestBlock[loopRepDepth] = testBlock;
1439 loopRepEndBlock[loopRepDepth] = endBlock;
1440
1441 // FIXME: jump(testBlock)
1442 Nucleus::createBr(testBlock);
1443 Nucleus::setInsertBlock(testBlock);
1444
Nicolas Capens7551ac62016-01-20 17:11:53 -05001445 branch(iteration[loopDepth] > 0, loopBlock, endBlock);
John Bauman89401822014-05-06 15:04:28 -04001446 Nucleus::setInsertBlock(loopBlock);
1447
Nicolas Capens7551ac62016-01-20 17:11:53 -05001448 iteration[loopDepth] = iteration[loopDepth] - 1; // FIXME: --
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001449
John Bauman89401822014-05-06 15:04:28 -04001450 loopRepDepth++;
John Bauman89401822014-05-06 15:04:28 -04001451 }
1452
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001453 void VertexProgram::REP(const Src &integerRegister)
John Bauman89401822014-05-06 15:04:28 -04001454 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001455 loopDepth++;
John Bauman89401822014-05-06 15:04:28 -04001456
Nicolas Capens7551ac62016-01-20 17:11:53 -05001457 iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
1458 aL[loopDepth] = aL[loopDepth - 1];
John Bauman89401822014-05-06 15:04:28 -04001459
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001460 BasicBlock *loopBlock = Nucleus::createBasicBlock();
1461 BasicBlock *testBlock = Nucleus::createBasicBlock();
1462 BasicBlock *endBlock = Nucleus::createBasicBlock();
John Bauman89401822014-05-06 15:04:28 -04001463
1464 loopRepTestBlock[loopRepDepth] = testBlock;
1465 loopRepEndBlock[loopRepDepth] = endBlock;
1466
1467 // FIXME: jump(testBlock)
1468 Nucleus::createBr(testBlock);
1469 Nucleus::setInsertBlock(testBlock);
1470
Nicolas Capens7551ac62016-01-20 17:11:53 -05001471 branch(iteration[loopDepth] > 0, loopBlock, endBlock);
John Bauman89401822014-05-06 15:04:28 -04001472 Nucleus::setInsertBlock(loopBlock);
1473
Nicolas Capens7551ac62016-01-20 17:11:53 -05001474 iteration[loopDepth] = iteration[loopDepth] - 1; // FIXME: --
John Bauman89401822014-05-06 15:04:28 -04001475
1476 loopRepDepth++;
John Bauman89401822014-05-06 15:04:28 -04001477 }
1478
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001479 void VertexProgram::WHILE(const Src &temporaryRegister)
John Bauman19bac1e2014-05-06 15:23:49 -04001480 {
Nicolas Capens7551ac62016-01-20 17:11:53 -05001481 enableIndex++;
John Bauman19bac1e2014-05-06 15:23:49 -04001482
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001483 BasicBlock *loopBlock = Nucleus::createBasicBlock();
1484 BasicBlock *testBlock = Nucleus::createBasicBlock();
1485 BasicBlock *endBlock = Nucleus::createBasicBlock();
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001486
John Bauman19bac1e2014-05-06 15:23:49 -04001487 loopRepTestBlock[loopRepDepth] = testBlock;
1488 loopRepEndBlock[loopRepDepth] = endBlock;
1489
Nicolas Capens7551ac62016-01-20 17:11:53 -05001490 Int4 restoreBreak = enableBreak;
Nicolas Capens2f490f02018-11-01 16:53:36 -04001491 restoreContinue.push_back(enableContinue);
John Bauman19bac1e2014-05-06 15:23:49 -04001492
Nicolas Capensd6bcc112018-01-08 14:09:51 -05001493 // TODO: jump(testBlock)
John Bauman19bac1e2014-05-06 15:23:49 -04001494 Nucleus::createBr(testBlock);
1495 Nucleus::setInsertBlock(testBlock);
John Bauman19bac1e2014-05-06 15:23:49 -04001496
Nicolas Capensc2534f42016-04-04 11:13:24 -04001497 const Vector4f &src = fetchRegister(temporaryRegister);
John Bauman19bac1e2014-05-06 15:23:49 -04001498 Int4 condition = As<Int4>(src.x);
Alexis Hetu48d47a42019-01-10 14:04:26 -05001499 condition &= enableStack[Min(enableIndex - 1, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Nicolas Capens2ff29482016-04-28 15:28:02 -04001500 if(shader->containsLeaveInstruction()) condition &= enableLeave;
Nicolas Capens6d123312018-01-08 12:57:52 -05001501 if(shader->containsBreakInstruction()) condition &= enableBreak;
Alexis Hetu48d47a42019-01-10 14:04:26 -05001502 enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
John Bauman19bac1e2014-05-06 15:23:49 -04001503
1504 Bool notAllFalse = SignMask(condition) != 0;
1505 branch(notAllFalse, loopBlock, endBlock);
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001506
John Bauman19bac1e2014-05-06 15:23:49 -04001507 Nucleus::setInsertBlock(endBlock);
Nicolas Capens7551ac62016-01-20 17:11:53 -05001508 enableBreak = restoreBreak;
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001509
John Bauman19bac1e2014-05-06 15:23:49 -04001510 Nucleus::setInsertBlock(loopBlock);
1511
1512 loopRepDepth++;
Nicolas Capens6e8ec332018-11-06 11:56:21 -05001513 scalar = false;
John Bauman19bac1e2014-05-06 15:23:49 -04001514 }
1515
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001516 void VertexProgram::SWITCH()
1517 {
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001518 BasicBlock *endBlock = Nucleus::createBasicBlock();
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001519
1520 loopRepTestBlock[loopRepDepth] = nullptr;
1521 loopRepEndBlock[loopRepDepth] = endBlock;
1522
Nicolas Capensd6bcc112018-01-08 14:09:51 -05001523 Int4 restoreBreak = enableBreak;
1524
1525 BasicBlock *currentBlock = Nucleus::getInsertBlock();
1526
1527 Nucleus::setInsertBlock(endBlock);
1528 enableBreak = restoreBreak;
1529
1530 Nucleus::setInsertBlock(currentBlock);
1531
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001532 loopRepDepth++;
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001533 }
1534
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001535 void VertexProgram::RET()
John Bauman89401822014-05-06 15:04:28 -04001536 {
John Bauman19bac1e2014-05-06 15:23:49 -04001537 if(currentLabel == -1)
John Bauman89401822014-05-06 15:04:28 -04001538 {
1539 returnBlock = Nucleus::createBasicBlock();
1540 Nucleus::createBr(returnBlock);
John Bauman89401822014-05-06 15:04:28 -04001541 }
1542 else
1543 {
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001544 BasicBlock *unreachableBlock = Nucleus::createBasicBlock();
John Bauman89401822014-05-06 15:04:28 -04001545
John Bauman19bac1e2014-05-06 15:23:49 -04001546 if(callRetBlock[currentLabel].size() > 1) // Pop the return destination from the call stack
John Bauman89401822014-05-06 15:04:28 -04001547 {
John Bauman19bac1e2014-05-06 15:23:49 -04001548 // FIXME: Encapsulate
Nicolas Capens7551ac62016-01-20 17:11:53 -05001549 UInt index = callStack[--stackIndex];
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001550
Nicolas Capens19336542016-09-26 10:32:29 -04001551 Value *value = index.loadValue();
Nicolas Capensb98fe5c2016-11-09 12:24:06 -05001552 SwitchCases *switchCases = Nucleus::createSwitch(value, unreachableBlock, (int)callRetBlock[currentLabel].size());
John Bauman19bac1e2014-05-06 15:23:49 -04001553
1554 for(unsigned int i = 0; i < callRetBlock[currentLabel].size(); i++)
1555 {
Nicolas Capensb98fe5c2016-11-09 12:24:06 -05001556 Nucleus::addSwitchCase(switchCases, i, callRetBlock[currentLabel][i]);
John Bauman19bac1e2014-05-06 15:23:49 -04001557 }
1558 }
1559 else if(callRetBlock[currentLabel].size() == 1) // Jump directly to the unique return destination
1560 {
1561 Nucleus::createBr(callRetBlock[currentLabel][0]);
1562 }
1563 else // Function isn't called
1564 {
1565 Nucleus::createBr(unreachableBlock);
John Bauman89401822014-05-06 15:04:28 -04001566 }
1567
1568 Nucleus::setInsertBlock(unreachableBlock);
1569 Nucleus::createUnreachable();
1570 }
1571 }
1572
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001573 void VertexProgram::LEAVE()
John Bauman89401822014-05-06 15:04:28 -04001574 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001575 enableLeave = enableLeave & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
John Bauman89401822014-05-06 15:04:28 -04001576
John Bauman19bac1e2014-05-06 15:23:49 -04001577 // FIXME: Return from function if all instances left
1578 // FIXME: Use enableLeave in other control-flow constructs
1579 }
John Bauman89401822014-05-06 15:04:28 -04001580
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001581 void VertexProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1)
John Bauman19bac1e2014-05-06 15:23:49 -04001582 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001583 dst = sampleTexture(src1, src0, (src0.x), (src0), (src0), (src0), Base);
John Bauman19bac1e2014-05-06 15:23:49 -04001584 }
1585
Nicolas Capensa0b57832017-11-07 13:07:53 -05001586 void VertexProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &offset)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001587 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001588 dst = sampleTexture(src1, src0, (src0.x), (src0), (src0), offset, {Base, Offset});
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001589 }
1590
Nicolas Capensa0b57832017-11-07 13:07:53 -05001591 void VertexProgram::TEXLOD(Vector4f &dst, Vector4f &src0, const Src& src1, Float4 &lod)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001592 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001593 dst = sampleTexture(src1, src0, lod, (src0), (src0), (src0), Lod);
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001594 }
1595
Nicolas Capensa0b57832017-11-07 13:07:53 -05001596 void VertexProgram::TEXLODOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &offset, Float4 &lod)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001597 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001598 dst = sampleTexture(src1, src0, lod, (src0), (src0), offset, {Lod, Offset});
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001599 }
1600
Nicolas Capensa0b57832017-11-07 13:07:53 -05001601 void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Float4 &lod)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001602 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001603 dst = sampleTexture(src1, src0, lod, (src0), (src0), (src0), Fetch);
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001604 }
1605
Nicolas Capensa0b57832017-11-07 13:07:53 -05001606 void VertexProgram::TEXELFETCHOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &offset, Float4 &lod)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001607 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001608 dst = sampleTexture(src1, src0, lod, (src0), (src0), offset, {Fetch, Offset});
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001609 }
1610
Nicolas Capensa0b57832017-11-07 13:07:53 -05001611 void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &dsx, Vector4f &dsy)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001612 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001613 dst = sampleTexture(src1, src0, (src0.x), dsx, dsy, src0, Grad);
1614 }
1615
1616 void VertexProgram::TEXGRADOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &dsx, Vector4f &dsy, Vector4f &offset)
1617 {
1618 dst = sampleTexture(src1, src0, (src0.x), dsx, dsy, offset, {Grad, Offset});
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001619 }
1620
Nicolas Capensb4fb3672016-01-15 17:02:41 -05001621 void VertexProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
Alexis Hetu9bcb31d2015-07-22 17:03:26 -04001622 {
Nicolas Capens79d0e562018-11-27 17:07:49 -05001623 bool uniformSampler = (src1.type == Shader::PARAMETER_SAMPLER && src1.rel.type == Shader::PARAMETER_VOID);
Nicolas Capensa9727582018-11-28 17:33:24 -05001624 Int offset = uniformSampler ? src1.index * sizeof(Texture) : As<Int>(Float(fetchRegister(src1).x.x)) * sizeof(Texture);
1625 Pointer<Byte> texture = data + OFFSET(DrawData, mipmap[TEXTURE_IMAGE_UNITS]) + offset;
Nicolas Capens79d0e562018-11-27 17:07:49 -05001626
Nicolas Capens89a218b2017-11-07 13:05:20 -05001627 dst = SamplerCore::textureSize(texture, lod);
Alexis Hetu9bcb31d2015-07-22 17:03:26 -04001628 }
1629
Nicolas Capensa0b57832017-11-07 13:07:53 -05001630 Vector4f VertexProgram::sampleTexture(const Src &s, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
John Bauman19bac1e2014-05-06 15:23:49 -04001631 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001632 Vector4f tmp;
1633
John Bauman19bac1e2014-05-06 15:23:49 -04001634 if(s.type == Shader::PARAMETER_SAMPLER && s.rel.type == Shader::PARAMETER_VOID)
1635 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001636 tmp = sampleTexture(s.index, uvwq, lod, dsx, dsy, offset, function);
John Bauman19bac1e2014-05-06 15:23:49 -04001637 }
1638 else
1639 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001640 Int index = As<Int>(Float(fetchRegister(s).x.x));
John Bauman19bac1e2014-05-06 15:23:49 -04001641
Nicolas Capensc2534f42016-04-04 11:13:24 -04001642 for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
John Bauman19bac1e2014-05-06 15:23:49 -04001643 {
1644 if(shader->usesSampler(i))
1645 {
1646 If(index == i)
1647 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001648 tmp = sampleTexture(i, uvwq, lod, dsx, dsy, offset, function);
John Bauman19bac1e2014-05-06 15:23:49 -04001649 // FIXME: When the sampler states are the same, we could use one sampler and just index the texture
1650 }
1651 }
1652 }
1653 }
Nicolas Capensc2534f42016-04-04 11:13:24 -04001654
Nicolas Capens89a218b2017-11-07 13:05:20 -05001655 Vector4f c;
Nicolas Capensc2534f42016-04-04 11:13:24 -04001656 c.x = tmp[(s.swizzle >> 0) & 0x3];
1657 c.y = tmp[(s.swizzle >> 2) & 0x3];
1658 c.z = tmp[(s.swizzle >> 4) & 0x3];
1659 c.w = tmp[(s.swizzle >> 6) & 0x3];
Nicolas Capens89a218b2017-11-07 13:05:20 -05001660
1661 return c;
1662 }
1663
Nicolas Capensa0b57832017-11-07 13:07:53 -05001664 Vector4f VertexProgram::sampleTexture(int sampler, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
Nicolas Capens89a218b2017-11-07 13:05:20 -05001665 {
1666 Pointer<Byte> texture = data + OFFSET(DrawData, mipmap[TEXTURE_IMAGE_UNITS]) + sampler * sizeof(Texture);
Nicolas Capensa0b57832017-11-07 13:07:53 -05001667 return SamplerCore(constants, state.sampler[sampler]).sampleTexture(texture, uvwq.x, uvwq.y, uvwq.z, uvwq.w, lod, dsx, dsy, offset, function);
John Bauman19bac1e2014-05-06 15:23:49 -04001668 }
John Bauman89401822014-05-06 15:04:28 -04001669}