blob: 843ba32fdffc842250d492fd2ed0e432edc9c105 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
Nicolas Capens5d961882016-01-01 23:18:14 -05002//
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
Nicolas Capens5d961882016-01-01 23:18:14 -05006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
Nicolas Capens5d961882016-01-01 23:18:14 -05008//
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.
Nicolas Capens5d961882016-01-01 23:18:14 -050014
15#include "PixelProgram.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040016
Nicolas Capens5d961882016-01-01 23:18:14 -050017#include "SamplerCore.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040018#include "Renderer/Primitive.hpp"
19#include "Renderer/Renderer.hpp"
Nicolas Capens5d961882016-01-01 23:18:14 -050020
21namespace sw
22{
23 extern bool postBlendSRGB;
Alexis Hetuf2a8c372015-07-13 11:08:41 -040024 extern bool booleanFaceRegister;
25 extern bool halfIntegerCoordinates; // Pixel centers are not at integer coordinates
Nicolas Capens5d961882016-01-01 23:18:14 -050026 extern bool fullPixelPositionRegister;
27
Ben Claytond951f192019-02-11 20:59:19 +000028 PixelProgram::PixelProgram(const PixelProcessor::State &state, const PixelShader *shader) :
29 PixelRoutine(state, shader),
30 r(shader->indirectAddressableTemporaries),
31 aL(shader->getLimits().loops),
32 increment(shader->getLimits().loops),
33 iteration(shader->getLimits().loops),
34 callStack(shader->getLimits().stack)
35 {
36 auto limits = shader->getLimits();
37 ifDepth.setLimit(limits.ifs);
38 loopRepDepth.setLimit(limits.loops);
39 currentLabel.setLimit(limits.functions);
40
41 ifFalseBlock.resize(limits.ifs);
42 loopRepTestBlock.resize(limits.loops);
43 loopRepEndBlock.resize(limits.loops);
44 labelBlock.resize(limits.functions);
45 isConditionalIf.resize(limits.ifs);
46
47 loopDepth = -1;
48 enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
49
50 if(shader->containsBreakInstruction())
51 {
52 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
53 }
54
55 if(shader->containsContinueInstruction())
56 {
57 enableContinue = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
58 }
59 }
60
Nicolas Capens4f172c72016-01-13 08:34:30 -050061 void PixelProgram::setBuiltins(Int &x, Int &y, Float4(&z)[4], Float4 &w)
Nicolas Capens5d961882016-01-01 23:18:14 -050062 {
Alexis Hetu53ad4af2017-12-06 14:49:07 -050063 if(shader->getShaderModel() >= 0x0300)
Alexis Hetuf2a8c372015-07-13 11:08:41 -040064 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040065 if(shader->isVPosDeclared())
Alexis Hetuf2a8c372015-07-13 11:08:41 -040066 {
67 if(!halfIntegerCoordinates)
68 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050069 vPos.x = Float4(Float(x)) + Float4(0, 1, 0, 1);
70 vPos.y = Float4(Float(y)) + Float4(0, 0, 1, 1);
Alexis Hetuf2a8c372015-07-13 11:08:41 -040071 }
72 else
73 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050074 vPos.x = Float4(Float(x)) + Float4(0.5f, 1.5f, 0.5f, 1.5f);
75 vPos.y = Float4(Float(y)) + Float4(0.5f, 0.5f, 1.5f, 1.5f);
Alexis Hetuf2a8c372015-07-13 11:08:41 -040076 }
77
78 if(fullPixelPositionRegister)
79 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050080 vPos.z = z[0]; // FIXME: Centroid?
81 vPos.w = w; // FIXME: Centroid?
Alexis Hetuf2a8c372015-07-13 11:08:41 -040082 }
83 }
84
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040085 if(shader->isVFaceDeclared())
Alexis Hetuf2a8c372015-07-13 11:08:41 -040086 {
Nicolas Capensdd4c8632018-07-31 15:33:28 -040087 Float4 face = *Pointer<Float>(primitive + OFFSET(Primitive, area));
88
89 if(booleanFaceRegister)
90 {
91 face = As<Float4>(state.frontFaceCCW ? CmpNLT(face, Float4(0.0f)) : CmpLT(face, Float4(0.0f)));
92 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -040093
Nicolas Capens4f172c72016-01-13 08:34:30 -050094 vFace.x = face;
95 vFace.y = face;
96 vFace.z = face;
97 vFace.w = face;
Alexis Hetuf2a8c372015-07-13 11:08:41 -040098 }
Nicolas Capens5d961882016-01-01 23:18:14 -050099 }
100 }
101
Nicolas Capens4f172c72016-01-13 08:34:30 -0500102 void PixelProgram::applyShader(Int cMask[4])
Nicolas Capens5d961882016-01-01 23:18:14 -0500103 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500104 enableIndex = 0;
105 stackIndex = 0;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400106
107 if(shader->containsLeaveInstruction())
108 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500109 enableLeave = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400110 }
111
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500112 for(int i = 0; i < RENDERTARGETS; i++)
113 {
114 if(state.targetFormat[i] != FORMAT_NULL)
115 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500116 oC[i] = Vector4f(0.0f, 0.0f, 0.0f, 0.0f);
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500117 }
118 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400119
120 // Create all call site return blocks up front
121 for(size_t i = 0; i < shader->getLength(); i++)
122 {
123 const Shader::Instruction *instruction = shader->getInstruction(i);
124 Shader::Opcode opcode = instruction->opcode;
125
126 if(opcode == Shader::OPCODE_CALL || opcode == Shader::OPCODE_CALLNZ)
127 {
128 const Dst &dst = instruction->dst;
129
130 ASSERT(callRetBlock[dst.label].size() == dst.callSite);
131 callRetBlock[dst.label].push_back(Nucleus::createBasicBlock());
132 }
133 }
134
Nicolas Capens8b124c12016-04-18 14:09:37 -0400135 bool broadcastColor0 = true;
136
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400137 for(size_t i = 0; i < shader->getLength(); i++)
138 {
139 const Shader::Instruction *instruction = shader->getInstruction(i);
140 Shader::Opcode opcode = instruction->opcode;
141
142 if(opcode == Shader::OPCODE_DCL || opcode == Shader::OPCODE_DEF || opcode == Shader::OPCODE_DEFI || opcode == Shader::OPCODE_DEFB)
143 {
144 continue;
145 }
146
147 const Dst &dst = instruction->dst;
148 const Src &src0 = instruction->src[0];
149 const Src &src1 = instruction->src[1];
150 const Src &src2 = instruction->src[2];
151 const Src &src3 = instruction->src[3];
Alexis Hetu25d47fc2015-10-22 13:58:32 -0400152 const Src &src4 = instruction->src[4];
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400153
154 bool predicate = instruction->predicate;
155 Control control = instruction->control;
156 bool pp = dst.partialPrecision;
157 bool project = instruction->project;
158 bool bias = instruction->bias;
159
160 Vector4f d;
161 Vector4f s0;
162 Vector4f s1;
163 Vector4f s2;
164 Vector4f s3;
Alexis Hetu25d47fc2015-10-22 13:58:32 -0400165 Vector4f s4;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400166
167 if(opcode == Shader::OPCODE_TEXKILL) // Takes destination as input
168 {
169 if(dst.type == Shader::PARAMETER_TEXTURE)
170 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500171 d.x = v[2 + dst.index].x;
172 d.y = v[2 + dst.index].y;
173 d.z = v[2 + dst.index].z;
174 d.w = v[2 + dst.index].w;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400175 }
176 else
177 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500178 d = r[dst.index];
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400179 }
180 }
181
Nicolas Capensc2534f42016-04-04 11:13:24 -0400182 if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
183 if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
184 if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
185 if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegister(src3);
186 if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegister(src4);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400187
188 switch(opcode)
189 {
190 case Shader::OPCODE_PS_2_0: break;
191 case Shader::OPCODE_PS_2_x: break;
192 case Shader::OPCODE_PS_3_0: break;
193 case Shader::OPCODE_DEF: break;
194 case Shader::OPCODE_DCL: break;
195 case Shader::OPCODE_NOP: break;
196 case Shader::OPCODE_MOV: mov(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400197 case Shader::OPCODE_NEG: neg(d, s0); break;
198 case Shader::OPCODE_INEG: ineg(d, s0); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400199 case Shader::OPCODE_F2B: f2b(d, s0); break;
200 case Shader::OPCODE_B2F: b2f(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400201 case Shader::OPCODE_F2I: f2i(d, s0); break;
202 case Shader::OPCODE_I2F: i2f(d, s0); break;
203 case Shader::OPCODE_F2U: f2u(d, s0); break;
204 case Shader::OPCODE_U2F: u2f(d, s0); break;
205 case Shader::OPCODE_I2B: i2b(d, s0); break;
206 case Shader::OPCODE_B2I: b2i(d, s0); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400207 case Shader::OPCODE_ADD: add(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400208 case Shader::OPCODE_IADD: iadd(d, s0, s1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400209 case Shader::OPCODE_SUB: sub(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400210 case Shader::OPCODE_ISUB: isub(d, s0, s1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400211 case Shader::OPCODE_MUL: mul(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400212 case Shader::OPCODE_IMUL: imul(d, s0, s1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400213 case Shader::OPCODE_MAD: mad(d, s0, s1, s2); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400214 case Shader::OPCODE_IMAD: imad(d, s0, s1, s2); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400215 case Shader::OPCODE_DP1: dp1(d, s0, s1); break;
216 case Shader::OPCODE_DP2: dp2(d, s0, s1); break;
217 case Shader::OPCODE_DP2ADD: dp2add(d, s0, s1, s2); break;
218 case Shader::OPCODE_DP3: dp3(d, s0, s1); break;
219 case Shader::OPCODE_DP4: dp4(d, s0, s1); break;
Alexis Hetuc3d95f32015-09-23 12:27:32 -0400220 case Shader::OPCODE_DET2: det2(d, s0, s1); break;
221 case Shader::OPCODE_DET3: det3(d, s0, s1, s2); break;
222 case Shader::OPCODE_DET4: det4(d, s0, s1, s2, s3); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400223 case Shader::OPCODE_CMP0: cmp0(d, s0, s1, s2); break;
224 case Shader::OPCODE_ICMP: icmp(d, s0, s1, control); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400225 case Shader::OPCODE_UCMP: ucmp(d, s0, s1, control); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400226 case Shader::OPCODE_SELECT: select(d, s0, s1, s2); break;
227 case Shader::OPCODE_EXTRACT: extract(d.x, s0, s1.x); break;
228 case Shader::OPCODE_INSERT: insert(d, s0, s1.x, s2.x); break;
229 case Shader::OPCODE_FRC: frc(d, s0); break;
230 case Shader::OPCODE_TRUNC: trunc(d, s0); break;
231 case Shader::OPCODE_FLOOR: floor(d, s0); break;
232 case Shader::OPCODE_ROUND: round(d, s0); break;
233 case Shader::OPCODE_ROUNDEVEN: roundEven(d, s0); break;
234 case Shader::OPCODE_CEIL: ceil(d, s0); break;
235 case Shader::OPCODE_EXP2X: exp2x(d, s0, pp); break;
236 case Shader::OPCODE_EXP2: exp2(d, s0, pp); break;
237 case Shader::OPCODE_LOG2X: log2x(d, s0, pp); break;
238 case Shader::OPCODE_LOG2: log2(d, s0, pp); break;
239 case Shader::OPCODE_EXP: exp(d, s0, pp); break;
240 case Shader::OPCODE_LOG: log(d, s0, pp); break;
241 case Shader::OPCODE_RCPX: rcpx(d, s0, pp); break;
242 case Shader::OPCODE_DIV: div(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400243 case Shader::OPCODE_IDIV: idiv(d, s0, s1); break;
244 case Shader::OPCODE_UDIV: udiv(d, s0, s1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400245 case Shader::OPCODE_MOD: mod(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400246 case Shader::OPCODE_IMOD: imod(d, s0, s1); break;
247 case Shader::OPCODE_UMOD: umod(d, s0, s1); break;
248 case Shader::OPCODE_SHL: shl(d, s0, s1); break;
249 case Shader::OPCODE_ISHR: ishr(d, s0, s1); break;
250 case Shader::OPCODE_USHR: ushr(d, s0, s1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400251 case Shader::OPCODE_RSQX: rsqx(d, s0, pp); break;
252 case Shader::OPCODE_SQRT: sqrt(d, s0, pp); break;
253 case Shader::OPCODE_RSQ: rsq(d, s0, pp); break;
254 case Shader::OPCODE_LEN2: len2(d.x, s0, pp); break;
255 case Shader::OPCODE_LEN3: len3(d.x, s0, pp); break;
256 case Shader::OPCODE_LEN4: len4(d.x, s0, pp); break;
257 case Shader::OPCODE_DIST1: dist1(d.x, s0, s1, pp); break;
258 case Shader::OPCODE_DIST2: dist2(d.x, s0, s1, pp); break;
259 case Shader::OPCODE_DIST3: dist3(d.x, s0, s1, pp); break;
260 case Shader::OPCODE_DIST4: dist4(d.x, s0, s1, pp); break;
261 case Shader::OPCODE_MIN: min(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400262 case Shader::OPCODE_IMIN: imin(d, s0, s1); break;
263 case Shader::OPCODE_UMIN: umin(d, s0, s1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400264 case Shader::OPCODE_MAX: max(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400265 case Shader::OPCODE_IMAX: imax(d, s0, s1); break;
266 case Shader::OPCODE_UMAX: umax(d, s0, s1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400267 case Shader::OPCODE_LRP: lrp(d, s0, s1, s2); break;
268 case Shader::OPCODE_STEP: step(d, s0, s1); break;
269 case Shader::OPCODE_SMOOTH: smooth(d, s0, s1, s2); break;
Alexis Hetu8ef6d102017-11-09 15:49:09 -0500270 case Shader::OPCODE_ISINF: isinf(d, s0); break;
271 case Shader::OPCODE_ISNAN: isnan(d, s0); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400272 case Shader::OPCODE_FLOATBITSTOINT:
273 case Shader::OPCODE_FLOATBITSTOUINT:
274 case Shader::OPCODE_INTBITSTOFLOAT:
275 case Shader::OPCODE_UINTBITSTOFLOAT: d = s0; break;
Alexis Hetu9cde9742016-04-06 13:03:38 -0400276 case Shader::OPCODE_PACKSNORM2x16: packSnorm2x16(d, s0); break;
277 case Shader::OPCODE_PACKUNORM2x16: packUnorm2x16(d, s0); break;
Alexis Hetuffb35eb2016-04-06 18:05:00 -0400278 case Shader::OPCODE_PACKHALF2x16: packHalf2x16(d, s0); break;
Alexis Hetu9cde9742016-04-06 13:03:38 -0400279 case Shader::OPCODE_UNPACKSNORM2x16: unpackSnorm2x16(d, s0); break;
280 case Shader::OPCODE_UNPACKUNORM2x16: unpackUnorm2x16(d, s0); break;
Alexis Hetuffb35eb2016-04-06 18:05:00 -0400281 case Shader::OPCODE_UNPACKHALF2x16: unpackHalf2x16(d, s0); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400282 case Shader::OPCODE_POWX: powx(d, s0, s1, pp); break;
283 case Shader::OPCODE_POW: pow(d, s0, s1, pp); break;
284 case Shader::OPCODE_SGN: sgn(d, s0); break;
Alexis Hetu0f448072016-03-18 10:56:08 -0400285 case Shader::OPCODE_ISGN: isgn(d, s0); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400286 case Shader::OPCODE_CRS: crs(d, s0, s1); break;
287 case Shader::OPCODE_FORWARD1: forward1(d, s0, s1, s2); break;
288 case Shader::OPCODE_FORWARD2: forward2(d, s0, s1, s2); break;
289 case Shader::OPCODE_FORWARD3: forward3(d, s0, s1, s2); break;
290 case Shader::OPCODE_FORWARD4: forward4(d, s0, s1, s2); break;
291 case Shader::OPCODE_REFLECT1: reflect1(d, s0, s1); break;
292 case Shader::OPCODE_REFLECT2: reflect2(d, s0, s1); break;
293 case Shader::OPCODE_REFLECT3: reflect3(d, s0, s1); break;
294 case Shader::OPCODE_REFLECT4: reflect4(d, s0, s1); break;
295 case Shader::OPCODE_REFRACT1: refract1(d, s0, s1, s2.x); break;
296 case Shader::OPCODE_REFRACT2: refract2(d, s0, s1, s2.x); break;
297 case Shader::OPCODE_REFRACT3: refract3(d, s0, s1, s2.x); break;
298 case Shader::OPCODE_REFRACT4: refract4(d, s0, s1, s2.x); break;
299 case Shader::OPCODE_NRM2: nrm2(d, s0, pp); break;
300 case Shader::OPCODE_NRM3: nrm3(d, s0, pp); break;
301 case Shader::OPCODE_NRM4: nrm4(d, s0, pp); break;
302 case Shader::OPCODE_ABS: abs(d, s0); break;
Alexis Hetu0f448072016-03-18 10:56:08 -0400303 case Shader::OPCODE_IABS: iabs(d, s0); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400304 case Shader::OPCODE_SINCOS: sincos(d, s0, pp); break;
305 case Shader::OPCODE_COS: cos(d, s0, pp); break;
306 case Shader::OPCODE_SIN: sin(d, s0, pp); break;
307 case Shader::OPCODE_TAN: tan(d, s0, pp); break;
308 case Shader::OPCODE_ACOS: acos(d, s0, pp); break;
309 case Shader::OPCODE_ASIN: asin(d, s0, pp); break;
310 case Shader::OPCODE_ATAN: atan(d, s0, pp); break;
311 case Shader::OPCODE_ATAN2: atan2(d, s0, s1, pp); break;
312 case Shader::OPCODE_COSH: cosh(d, s0, pp); break;
313 case Shader::OPCODE_SINH: sinh(d, s0, pp); break;
314 case Shader::OPCODE_TANH: tanh(d, s0, pp); break;
315 case Shader::OPCODE_ACOSH: acosh(d, s0, pp); break;
316 case Shader::OPCODE_ASINH: asinh(d, s0, pp); break;
317 case Shader::OPCODE_ATANH: atanh(d, s0, pp); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500318 case Shader::OPCODE_M4X4: M4X4(d, s0, src1); break;
319 case Shader::OPCODE_M4X3: M4X3(d, s0, src1); break;
320 case Shader::OPCODE_M3X4: M3X4(d, s0, src1); break;
321 case Shader::OPCODE_M3X3: M3X3(d, s0, src1); break;
322 case Shader::OPCODE_M3X2: M3X2(d, s0, src1); break;
Nicolas Capensa0b57832017-11-07 13:07:53 -0500323 case Shader::OPCODE_TEX: TEX(d, s0, src1, project, bias); break;
324 case Shader::OPCODE_TEXLDD: TEXGRAD(d, s0, src1, s2, s3); break;
325 case Shader::OPCODE_TEXLDL: TEXLOD(d, s0, src1, s0.w); break;
326 case Shader::OPCODE_TEXLOD: TEXLOD(d, s0, src1, s2.x); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500327 case Shader::OPCODE_TEXSIZE: TEXSIZE(d, s0.x, src1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400328 case Shader::OPCODE_TEXKILL: TEXKILL(cMask, d, dst.mask); break;
Nicolas Capensa0b57832017-11-07 13:07:53 -0500329 case Shader::OPCODE_TEXOFFSET: TEXOFFSET(d, s0, src1, s2); break;
330 case Shader::OPCODE_TEXLODOFFSET: TEXLODOFFSET(d, s0, src1, s2, s3.x); break;
331 case Shader::OPCODE_TEXELFETCH: TEXELFETCH(d, s0, src1, s2.x); break;
332 case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCHOFFSET(d, s0, src1, s2, s3.x); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500333 case Shader::OPCODE_TEXGRAD: TEXGRAD(d, s0, src1, s2, s3); break;
Nicolas Capensa0b57832017-11-07 13:07:53 -0500334 case Shader::OPCODE_TEXGRADOFFSET: TEXGRADOFFSET(d, s0, src1, s2, s3, s4); break;
335 case Shader::OPCODE_TEXBIAS: TEXBIAS(d, s0, src1, s2.x); break;
336 case Shader::OPCODE_TEXOFFSETBIAS: TEXOFFSETBIAS(d, s0, src1, s2, s3.x); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500337 case Shader::OPCODE_DISCARD: DISCARD(cMask, instruction); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400338 case Shader::OPCODE_DFDX: DFDX(d, s0); break;
339 case Shader::OPCODE_DFDY: DFDY(d, s0); break;
340 case Shader::OPCODE_FWIDTH: FWIDTH(d, s0); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500341 case Shader::OPCODE_BREAK: BREAK(); break;
342 case Shader::OPCODE_BREAKC: BREAKC(s0, s1, control); break;
343 case Shader::OPCODE_BREAKP: BREAKP(src0); break;
344 case Shader::OPCODE_CONTINUE: CONTINUE(); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400345 case Shader::OPCODE_TEST: TEST(); break;
Nicolas Capens6e8ec332018-11-06 11:56:21 -0500346 case Shader::OPCODE_SCALAR: SCALAR(); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500347 case Shader::OPCODE_CALL: CALL(dst.label, dst.callSite); break;
348 case Shader::OPCODE_CALLNZ: CALLNZ(dst.label, dst.callSite, src0); break;
349 case Shader::OPCODE_ELSE: ELSE(); break;
350 case Shader::OPCODE_ENDIF: ENDIF(); break;
351 case Shader::OPCODE_ENDLOOP: ENDLOOP(); break;
352 case Shader::OPCODE_ENDREP: ENDREP(); break;
353 case Shader::OPCODE_ENDWHILE: ENDWHILE(); break;
Alexis Hetu9aa83a92016-05-02 17:34:46 -0400354 case Shader::OPCODE_ENDSWITCH: ENDSWITCH(); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500355 case Shader::OPCODE_IF: IF(src0); break;
356 case Shader::OPCODE_IFC: IFC(s0, s1, control); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400357 case Shader::OPCODE_LABEL: LABEL(dst.index); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500358 case Shader::OPCODE_LOOP: LOOP(src1); break;
359 case Shader::OPCODE_REP: REP(src0); break;
360 case Shader::OPCODE_WHILE: WHILE(src0); break;
Alexis Hetu9aa83a92016-05-02 17:34:46 -0400361 case Shader::OPCODE_SWITCH: SWITCH(); break;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500362 case Shader::OPCODE_RET: RET(); break;
363 case Shader::OPCODE_LEAVE: LEAVE(); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400364 case Shader::OPCODE_CMP: cmp(d, s0, s1, control); break;
365 case Shader::OPCODE_ALL: all(d.x, s0); break;
366 case Shader::OPCODE_ANY: any(d.x, s0); break;
Alexis Hetu24f454e2016-08-31 17:22:13 -0400367 case Shader::OPCODE_NOT: bitwise_not(d, s0); break;
368 case Shader::OPCODE_OR: bitwise_or(d, s0, s1); break;
369 case Shader::OPCODE_XOR: bitwise_xor(d, s0, s1); break;
370 case Shader::OPCODE_AND: bitwise_and(d, s0, s1); break;
Alexis Hetu8d78cf72015-08-28 14:24:45 -0400371 case Shader::OPCODE_EQ: equal(d, s0, s1); break;
372 case Shader::OPCODE_NE: notEqual(d, s0, s1); break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400373 case Shader::OPCODE_END: break;
374 default:
375 ASSERT(false);
376 }
377
378 if(dst.type != Shader::PARAMETER_VOID && dst.type != Shader::PARAMETER_LABEL && opcode != Shader::OPCODE_TEXKILL && opcode != Shader::OPCODE_NOP)
379 {
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400380 if(dst.saturate)
381 {
382 if(dst.x) d.x = Max(d.x, Float4(0.0f));
383 if(dst.y) d.y = Max(d.y, Float4(0.0f));
384 if(dst.z) d.z = Max(d.z, Float4(0.0f));
385 if(dst.w) d.w = Max(d.w, Float4(0.0f));
386
387 if(dst.x) d.x = Min(d.x, Float4(1.0f));
388 if(dst.y) d.y = Min(d.y, Float4(1.0f));
389 if(dst.z) d.z = Min(d.z, Float4(1.0f));
390 if(dst.w) d.w = Min(d.w, Float4(1.0f));
391 }
392
393 if(instruction->isPredicated())
394 {
395 Vector4f pDst; // FIXME: Rename
396
397 switch(dst.type)
398 {
399 case Shader::PARAMETER_TEMP:
400 if(dst.rel.type == Shader::PARAMETER_VOID)
401 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500402 if(dst.x) pDst.x = r[dst.index].x;
403 if(dst.y) pDst.y = r[dst.index].y;
404 if(dst.z) pDst.z = r[dst.index].z;
405 if(dst.w) pDst.w = r[dst.index].w;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400406 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400407 else if(!dst.rel.dynamic)
408 {
409 Int a = dst.index + relativeAddress(dst.rel);
410
411 if(dst.x) pDst.x = r[a].x;
412 if(dst.y) pDst.y = r[a].y;
413 if(dst.z) pDst.z = r[a].z;
414 if(dst.w) pDst.w = r[a].w;
415 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400416 else
417 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400418 Int4 a = dst.index + dynamicAddress(dst.rel);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400419
Nicolas Capens4b743732018-05-28 13:22:07 -0400420 if(dst.x) pDst.x = r[a].x;
421 if(dst.y) pDst.y = r[a].y;
422 if(dst.z) pDst.z = r[a].z;
423 if(dst.w) pDst.w = r[a].w;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400424 }
425 break;
426 case Shader::PARAMETER_COLOROUT:
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500427 if(dst.rel.type == Shader::PARAMETER_VOID)
428 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500429 if(dst.x) pDst.x = oC[dst.index].x;
430 if(dst.y) pDst.y = oC[dst.index].y;
431 if(dst.z) pDst.z = oC[dst.index].z;
432 if(dst.w) pDst.w = oC[dst.index].w;
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500433 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400434 else if(!dst.rel.dynamic)
435 {
436 Int a = dst.index + relativeAddress(dst.rel);
437
438 if(dst.x) pDst.x = oC[a].x;
439 if(dst.y) pDst.y = oC[a].y;
440 if(dst.z) pDst.z = oC[a].z;
441 if(dst.w) pDst.w = oC[a].w;
442 }
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500443 else
444 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400445 Int4 a = dst.index + dynamicAddress(dst.rel);
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500446
Nicolas Capens4f172c72016-01-13 08:34:30 -0500447 if(dst.x) pDst.x = oC[a].x;
448 if(dst.y) pDst.y = oC[a].y;
449 if(dst.z) pDst.z = oC[a].z;
450 if(dst.w) pDst.w = oC[a].w;
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500451 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400452 break;
453 case Shader::PARAMETER_PREDICATE:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500454 if(dst.x) pDst.x = p0.x;
455 if(dst.y) pDst.y = p0.y;
456 if(dst.z) pDst.z = p0.z;
457 if(dst.w) pDst.w = p0.w;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400458 break;
459 case Shader::PARAMETER_DEPTHOUT:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500460 pDst.x = oDepth;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400461 break;
462 default:
463 ASSERT(false);
464 }
465
Nicolas Capens4f172c72016-01-13 08:34:30 -0500466 Int4 enable = enableMask(instruction);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400467
468 Int4 xEnable = enable;
469 Int4 yEnable = enable;
470 Int4 zEnable = enable;
471 Int4 wEnable = enable;
472
473 if(predicate)
474 {
475 unsigned char pSwizzle = instruction->predicateSwizzle;
476
Nicolas Capens4f172c72016-01-13 08:34:30 -0500477 Float4 xPredicate = p0[(pSwizzle >> 0) & 0x03];
478 Float4 yPredicate = p0[(pSwizzle >> 2) & 0x03];
479 Float4 zPredicate = p0[(pSwizzle >> 4) & 0x03];
480 Float4 wPredicate = p0[(pSwizzle >> 6) & 0x03];
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400481
482 if(!instruction->predicateNot)
483 {
484 if(dst.x) xEnable = xEnable & As<Int4>(xPredicate);
485 if(dst.y) yEnable = yEnable & As<Int4>(yPredicate);
486 if(dst.z) zEnable = zEnable & As<Int4>(zPredicate);
487 if(dst.w) wEnable = wEnable & As<Int4>(wPredicate);
488 }
489 else
490 {
491 if(dst.x) xEnable = xEnable & ~As<Int4>(xPredicate);
492 if(dst.y) yEnable = yEnable & ~As<Int4>(yPredicate);
493 if(dst.z) zEnable = zEnable & ~As<Int4>(zPredicate);
494 if(dst.w) wEnable = wEnable & ~As<Int4>(wPredicate);
495 }
496 }
497
498 if(dst.x) d.x = As<Float4>(As<Int4>(d.x) & xEnable);
499 if(dst.y) d.y = As<Float4>(As<Int4>(d.y) & yEnable);
500 if(dst.z) d.z = As<Float4>(As<Int4>(d.z) & zEnable);
501 if(dst.w) d.w = As<Float4>(As<Int4>(d.w) & wEnable);
502
503 if(dst.x) d.x = As<Float4>(As<Int4>(d.x) | (As<Int4>(pDst.x) & ~xEnable));
504 if(dst.y) d.y = As<Float4>(As<Int4>(d.y) | (As<Int4>(pDst.y) & ~yEnable));
505 if(dst.z) d.z = As<Float4>(As<Int4>(d.z) | (As<Int4>(pDst.z) & ~zEnable));
506 if(dst.w) d.w = As<Float4>(As<Int4>(d.w) | (As<Int4>(pDst.w) & ~wEnable));
507 }
508
509 switch(dst.type)
510 {
511 case Shader::PARAMETER_TEMP:
512 if(dst.rel.type == Shader::PARAMETER_VOID)
513 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500514 if(dst.x) r[dst.index].x = d.x;
515 if(dst.y) r[dst.index].y = d.y;
516 if(dst.z) r[dst.index].z = d.z;
517 if(dst.w) r[dst.index].w = d.w;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400518 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400519 else if(!dst.rel.dynamic)
520 {
521 Int a = dst.index + relativeAddress(dst.rel);
522
523 if(dst.x) r[a].x = d.x;
524 if(dst.y) r[a].y = d.y;
525 if(dst.z) r[a].z = d.z;
526 if(dst.w) r[a].w = d.w;
527 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400528 else
529 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400530 Int4 a = dst.index + dynamicAddress(dst.rel);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400531
Nicolas Capens4b743732018-05-28 13:22:07 -0400532 if(dst.x) r.scatter_x(a, d.x);
533 if(dst.y) r.scatter_y(a, d.y);
534 if(dst.z) r.scatter_z(a, d.z);
535 if(dst.w) r.scatter_w(a, d.w);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400536 }
537 break;
538 case Shader::PARAMETER_COLOROUT:
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500539 if(dst.rel.type == Shader::PARAMETER_VOID)
540 {
Nicolas Capens8b124c12016-04-18 14:09:37 -0400541 broadcastColor0 = (dst.index == 0) && broadcastColor0;
542
Nicolas Capens4b743732018-05-28 13:22:07 -0400543 if(dst.x) oC[dst.index].x = d.x;
544 if(dst.y) oC[dst.index].y = d.y;
545 if(dst.z) oC[dst.index].z = d.z;
546 if(dst.w) oC[dst.index].w = d.w;
547 }
548 else if(!dst.rel.dynamic)
549 {
550 broadcastColor0 = false;
551 Int a = dst.index + relativeAddress(dst.rel);
552
553 if(dst.x) oC[a].x = d.x;
554 if(dst.y) oC[a].y = d.y;
555 if(dst.z) oC[a].z = d.z;
556 if(dst.w) oC[a].w = d.w;
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500557 }
558 else
559 {
Nicolas Capens8b124c12016-04-18 14:09:37 -0400560 broadcastColor0 = false;
Nicolas Capens4b743732018-05-28 13:22:07 -0400561 Int4 a = dst.index + dynamicAddress(dst.rel);
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500562
Nicolas Capens4b743732018-05-28 13:22:07 -0400563 if(dst.x) oC.scatter_x(a, d.x);
564 if(dst.y) oC.scatter_y(a, d.y);
565 if(dst.z) oC.scatter_z(a, d.z);
566 if(dst.w) oC.scatter_w(a, d.w);
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500567 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400568 break;
569 case Shader::PARAMETER_PREDICATE:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500570 if(dst.x) p0.x = d.x;
571 if(dst.y) p0.y = d.y;
572 if(dst.z) p0.z = d.z;
573 if(dst.w) p0.w = d.w;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400574 break;
575 case Shader::PARAMETER_DEPTHOUT:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500576 oDepth = d.x;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400577 break;
578 default:
579 ASSERT(false);
580 }
581 }
582 }
583
584 if(currentLabel != -1)
585 {
586 Nucleus::setInsertBlock(returnBlock);
587 }
588
Nicolas Capens8b124c12016-04-18 14:09:37 -0400589 if(broadcastColor0)
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400590 {
Nicolas Capens8b124c12016-04-18 14:09:37 -0400591 for(int i = 0; i < RENDERTARGETS; i++)
592 {
593 c[i] = oC[0];
594 }
595 }
596 else
597 {
598 for(int i = 0; i < RENDERTARGETS; i++)
599 {
600 c[i] = oC[i];
601 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400602 }
Nicolas Capens7bc079c2018-01-02 15:55:11 -0500603
604 clampColor(c);
605
606 if(state.depthOverride)
607 {
608 oDepth = Min(Max(oDepth, Float4(0.0f)), Float4(1.0f));
609 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400610 }
Nicolas Capens5d961882016-01-01 23:18:14 -0500611
Nicolas Capens4f172c72016-01-13 08:34:30 -0500612 Bool PixelProgram::alphaTest(Int cMask[4])
Nicolas Capens5d961882016-01-01 23:18:14 -0500613 {
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400614 if(!state.alphaTestActive())
615 {
616 return true;
617 }
618
619 Int aMask;
620
621 if(state.transparencyAntialiasing == TRANSPARENCY_NONE)
622 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500623 Short4 alpha = RoundShort4(c[0].w * Float4(0x1000));
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400624
Nicolas Capens4f172c72016-01-13 08:34:30 -0500625 PixelRoutine::alphaTest(aMask, alpha);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400626
627 for(unsigned int q = 0; q < state.multiSample; q++)
628 {
629 cMask[q] &= aMask;
630 }
631 }
632 else if(state.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
633 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500634 alphaToCoverage(cMask, c[0].w);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400635 }
636 else ASSERT(false);
637
638 Int pass = cMask[0];
639
640 for(unsigned int q = 1; q < state.multiSample; q++)
641 {
642 pass = pass | cMask[q];
643 }
644
Nicolas Capens5d961882016-01-01 23:18:14 -0500645 return pass != 0x0;
646 }
647
Nicolas Capens4f172c72016-01-13 08:34:30 -0500648 void PixelProgram::rasterOperation(Float4 &fog, Pointer<Byte> cBuffer[4], Int &x, Int sMask[4], Int zMask[4], Int cMask[4])
Nicolas Capens5d961882016-01-01 23:18:14 -0500649 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500650 for(int index = 0; index < RENDERTARGETS; index++)
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400651 {
652 if(!state.colorWriteActive(index))
653 {
654 continue;
Nicolas Capens5d961882016-01-01 23:18:14 -0500655 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400656
Alexis Hetu049a1872016-04-25 16:59:58 -0400657 if(!postBlendSRGB && state.writeSRGB && !isSRGB(index))
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400658 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500659 c[index].x = linearToSRGB(c[index].x);
660 c[index].y = linearToSRGB(c[index].y);
661 c[index].z = linearToSRGB(c[index].z);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400662 }
663
664 if(index == 0)
665 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500666 fogBlend(c[index], fog);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400667 }
668
669 switch(state.targetFormat[index])
670 {
671 case FORMAT_R5G6B5:
672 case FORMAT_X8R8G8B8:
673 case FORMAT_X8B8G8R8:
674 case FORMAT_A8R8G8B8:
675 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400676 case FORMAT_SRGB8_X8:
677 case FORMAT_SRGB8_A8:
Alexis Hetu143dfc72016-09-13 18:41:27 -0400678 case FORMAT_G8R8:
Alexis Hetu0cff3cb2016-05-04 16:23:50 -0400679 case FORMAT_R8:
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400680 case FORMAT_A8:
681 case FORMAT_G16R16:
682 case FORMAT_A16B16G16R16:
683 for(unsigned int q = 0; q < state.multiSample; q++)
684 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500685 Pointer<Byte> buffer = cBuffer[index] + q * *Pointer<Int>(data + OFFSET(DrawData, colorSliceB[index]));
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400686 Vector4s color;
687
Nicolas Capens13c70cd2016-04-05 10:51:45 -0400688 if(state.targetFormat[index] == FORMAT_R5G6B5)
689 {
690 color.x = UShort4(c[index].x * Float4(0xFBFF), false);
691 color.y = UShort4(c[index].y * Float4(0xFDFF), false);
692 color.z = UShort4(c[index].z * Float4(0xFBFF), false);
693 color.w = UShort4(c[index].w * Float4(0xFFFF), false);
694 }
695 else
696 {
697 color.x = convertFixed16(c[index].x, false);
698 color.y = convertFixed16(c[index].y, false);
699 color.z = convertFixed16(c[index].z, false);
700 color.w = convertFixed16(c[index].w, false);
701 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400702
703 if(state.multiSampleMask & (1 << q))
704 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500705 alphaBlend(index, buffer, color, x);
706 logicOperation(index, buffer, color, x);
707 writeColor(index, buffer, x, color, sMask[q], zMask[q], cMask[q]);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400708 }
709 }
710 break;
711 case FORMAT_R32F:
712 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400713 case FORMAT_X32B32G32R32F:
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400714 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -0500715 case FORMAT_X32B32G32R32F_UNSIGNED:
Alexis Hetu1abb6382016-02-08 11:21:16 -0500716 case FORMAT_R32I:
717 case FORMAT_G32R32I:
718 case FORMAT_A32B32G32R32I:
719 case FORMAT_R32UI:
720 case FORMAT_G32R32UI:
721 case FORMAT_A32B32G32R32UI:
Alexis Hetubd7117d2016-06-02 10:35:59 -0400722 case FORMAT_R16I:
723 case FORMAT_G16R16I:
724 case FORMAT_A16B16G16R16I:
725 case FORMAT_R16UI:
726 case FORMAT_G16R16UI:
727 case FORMAT_A16B16G16R16UI:
728 case FORMAT_R8I:
729 case FORMAT_G8R8I:
730 case FORMAT_A8B8G8R8I:
731 case FORMAT_R8UI:
732 case FORMAT_G8R8UI:
733 case FORMAT_A8B8G8R8UI:
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400734 for(unsigned int q = 0; q < state.multiSample; q++)
735 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500736 Pointer<Byte> buffer = cBuffer[index] + q * *Pointer<Int>(data + OFFSET(DrawData, colorSliceB[index]));
737 Vector4f color = c[index];
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400738
739 if(state.multiSampleMask & (1 << q))
740 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500741 alphaBlend(index, buffer, color, x);
742 writeColor(index, buffer, x, color, sMask[q], zMask[q], cMask[q]);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400743 }
744 }
745 break;
746 default:
747 ASSERT(false);
748 }
749 }
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500750 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400751
Nicolas Capensa0b57832017-11-07 13:07:53 -0500752 Vector4f PixelProgram::sampleTexture(const Src &sampler, Vector4f &uvwq, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400753 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400754 Vector4f tmp;
755
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400756 if(sampler.type == Shader::PARAMETER_SAMPLER && sampler.rel.type == Shader::PARAMETER_VOID)
757 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500758 tmp = sampleTexture(sampler.index, uvwq, bias, dsx, dsy, offset, function);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400759 }
760 else
761 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400762 Int index = As<Int>(Float(fetchRegister(sampler).x.x));
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400763
764 for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
765 {
766 if(shader->usesSampler(i))
767 {
768 If(index == i)
769 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500770 tmp = sampleTexture(i, uvwq, bias, dsx, dsy, offset, function);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400771 // FIXME: When the sampler states are the same, we could use one sampler and just index the texture
772 }
773 }
774 }
775 }
Nicolas Capensc2534f42016-04-04 11:13:24 -0400776
Nicolas Capens89a218b2017-11-07 13:05:20 -0500777 Vector4f c;
Nicolas Capensc2534f42016-04-04 11:13:24 -0400778 c.x = tmp[(sampler.swizzle >> 0) & 0x3];
779 c.y = tmp[(sampler.swizzle >> 2) & 0x3];
780 c.z = tmp[(sampler.swizzle >> 4) & 0x3];
781 c.w = tmp[(sampler.swizzle >> 6) & 0x3];
Nicolas Capens89a218b2017-11-07 13:05:20 -0500782
783 return c;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400784 }
785
Nicolas Capensa0b57832017-11-07 13:07:53 -0500786 Vector4f PixelProgram::sampleTexture(int samplerIndex, Vector4f &uvwq, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400787 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400788 #if PERF_PROFILE
789 Long texTime = Ticks();
790 #endif
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400791
Meng-Lin Wu2337a192016-06-01 13:54:07 -0400792 Pointer<Byte> texture = data + OFFSET(DrawData, mipmap) + samplerIndex * sizeof(Texture);
Nicolas Capensa0b57832017-11-07 13:07:53 -0500793 Vector4f c = SamplerCore(constants, state.sampler[samplerIndex]).sampleTexture(texture, uvwq.x, uvwq.y, uvwq.z, uvwq.w, bias, dsx, dsy, offset, function);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400794
Nicolas Capensc2534f42016-04-04 11:13:24 -0400795 #if PERF_PROFILE
796 cycles[PERF_TEX] += Ticks() - texTime;
797 #endif
Nicolas Capens89a218b2017-11-07 13:05:20 -0500798
799 return c;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400800 }
801
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500802 void PixelProgram::clampColor(Vector4f oC[RENDERTARGETS])
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400803 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500804 for(int index = 0; index < RENDERTARGETS; index++)
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400805 {
806 if(!state.colorWriteActive(index) && !(index == 0 && state.alphaTestActive()))
807 {
808 continue;
809 }
810
811 switch(state.targetFormat[index])
812 {
813 case FORMAT_NULL:
814 break;
815 case FORMAT_R5G6B5:
816 case FORMAT_A8R8G8B8:
817 case FORMAT_A8B8G8R8:
818 case FORMAT_X8R8G8B8:
819 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400820 case FORMAT_SRGB8_X8:
821 case FORMAT_SRGB8_A8:
Alexis Hetu143dfc72016-09-13 18:41:27 -0400822 case FORMAT_G8R8:
Alexis Hetu0cff3cb2016-05-04 16:23:50 -0400823 case FORMAT_R8:
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400824 case FORMAT_A8:
825 case FORMAT_G16R16:
826 case FORMAT_A16B16G16R16:
827 oC[index].x = Max(oC[index].x, Float4(0.0f)); oC[index].x = Min(oC[index].x, Float4(1.0f));
828 oC[index].y = Max(oC[index].y, Float4(0.0f)); oC[index].y = Min(oC[index].y, Float4(1.0f));
829 oC[index].z = Max(oC[index].z, Float4(0.0f)); oC[index].z = Min(oC[index].z, Float4(1.0f));
830 oC[index].w = Max(oC[index].w, Float4(0.0f)); oC[index].w = Min(oC[index].w, Float4(1.0f));
831 break;
832 case FORMAT_R32F:
833 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400834 case FORMAT_X32B32G32R32F:
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400835 case FORMAT_A32B32G32R32F:
Alexis Hetu1abb6382016-02-08 11:21:16 -0500836 case FORMAT_R32I:
837 case FORMAT_G32R32I:
838 case FORMAT_A32B32G32R32I:
839 case FORMAT_R32UI:
840 case FORMAT_G32R32UI:
841 case FORMAT_A32B32G32R32UI:
Alexis Hetu8e7675d2016-09-27 21:06:00 -0400842 case FORMAT_R16I:
843 case FORMAT_G16R16I:
844 case FORMAT_A16B16G16R16I:
845 case FORMAT_R16UI:
846 case FORMAT_G16R16UI:
847 case FORMAT_A16B16G16R16UI:
848 case FORMAT_R8I:
849 case FORMAT_G8R8I:
850 case FORMAT_A8B8G8R8I:
851 case FORMAT_R8UI:
852 case FORMAT_G8R8UI:
853 case FORMAT_A8B8G8R8UI:
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400854 break;
Nicolas Capens67fdd832017-12-21 11:20:54 -0500855 case FORMAT_X32B32G32R32F_UNSIGNED:
856 oC[index].x = Max(oC[index].x, Float4(0.0f));
857 oC[index].y = Max(oC[index].y, Float4(0.0f));
858 oC[index].z = Max(oC[index].z, Float4(0.0f));
859 oC[index].w = Max(oC[index].w, Float4(0.0f));
860 break;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400861 default:
862 ASSERT(false);
863 }
864 }
865 }
866
Nicolas Capens4f172c72016-01-13 08:34:30 -0500867 Int4 PixelProgram::enableMask(const Shader::Instruction *instruction)
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400868 {
Nicolas Capens6e8ec332018-11-06 11:56:21 -0500869 if(scalar)
870 {
871 return Int4(0xFFFFFFFF);
872 }
873
Alexis Hetu48d47a42019-01-10 14:04:26 -0500874 Int4 enable = instruction->analysisBranch ? Int4(enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))]) : Int4(0xFFFFFFFF);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400875
Nicolas Capens8a587712018-10-20 14:17:49 -0400876 if(shader->containsBreakInstruction() && instruction->analysisBreak)
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400877 {
Nicolas Capens8a587712018-10-20 14:17:49 -0400878 enable &= enableBreak;
879 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400880
Nicolas Capens8a587712018-10-20 14:17:49 -0400881 if(shader->containsContinueInstruction() && instruction->analysisContinue)
882 {
883 enable &= enableContinue;
884 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400885
Nicolas Capens8a587712018-10-20 14:17:49 -0400886 if(shader->containsLeaveInstruction() && instruction->analysisLeave)
887 {
888 enable &= enableLeave;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400889 }
890
891 return enable;
892 }
893
Nicolas Capensc2534f42016-04-04 11:13:24 -0400894 Vector4f PixelProgram::fetchRegister(const Src &src, unsigned int offset)
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400895 {
896 Vector4f reg;
Nicolas Capens5d961882016-01-01 23:18:14 -0500897 unsigned int i = src.index + offset;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400898
899 switch(src.type)
900 {
901 case Shader::PARAMETER_TEMP:
902 if(src.rel.type == Shader::PARAMETER_VOID)
903 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500904 reg = r[i];
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400905 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400906 else if(!src.rel.dynamic)
907 {
908 reg = r[i + relativeAddress(src.rel, src.bufferIndex)];
909 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400910 else
911 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400912 reg = r[i + dynamicAddress(src.rel)];
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400913 }
914 break;
915 case Shader::PARAMETER_INPUT:
Nicolas Capens4b743732018-05-28 13:22:07 -0400916 if(src.rel.type == Shader::PARAMETER_VOID) // Not relative
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400917 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400918 reg = v[i];
919 }
920 else if(!src.rel.dynamic)
921 {
922 reg = v[i + relativeAddress(src.rel, src.bufferIndex)];
923 }
924 else
925 {
926 reg = v[i + dynamicAddress(src.rel)];
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400927 }
928 break;
929 case Shader::PARAMETER_CONST:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500930 reg = readConstant(src, offset);
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400931 break;
932 case Shader::PARAMETER_TEXTURE:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500933 reg = v[2 + i];
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400934 break;
935 case Shader::PARAMETER_MISCTYPE:
Alexis Hetu877ddfc2017-07-25 17:48:00 -0400936 if(src.index == Shader::VPosIndex) reg = vPos;
937 if(src.index == Shader::VFaceIndex) reg = vFace;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400938 break;
939 case Shader::PARAMETER_SAMPLER:
940 if(src.rel.type == Shader::PARAMETER_VOID)
941 {
942 reg.x = As<Float4>(Int4(i));
943 }
944 else if(src.rel.type == Shader::PARAMETER_TEMP)
945 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500946 reg.x = As<Float4>(Int4(i) + As<Int4>(r[src.rel.index].x));
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400947 }
948 return reg;
949 case Shader::PARAMETER_PREDICATE: return reg; // Dummy
950 case Shader::PARAMETER_VOID: return reg; // Dummy
951 case Shader::PARAMETER_FLOAT4LITERAL:
952 reg.x = Float4(src.value[0]);
953 reg.y = Float4(src.value[1]);
954 reg.z = Float4(src.value[2]);
955 reg.w = Float4(src.value[3]);
956 break;
957 case Shader::PARAMETER_CONSTINT: return reg; // Dummy
958 case Shader::PARAMETER_CONSTBOOL: return reg; // Dummy
959 case Shader::PARAMETER_LOOP: return reg; // Dummy
960 case Shader::PARAMETER_COLOROUT:
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500961 if(src.rel.type == Shader::PARAMETER_VOID) // Not relative
962 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500963 reg = oC[i];
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500964 }
Nicolas Capens4b743732018-05-28 13:22:07 -0400965 else if(!src.rel.dynamic)
966 {
967 reg = oC[i + relativeAddress(src.rel, src.bufferIndex)];
968 }
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500969 else
970 {
Nicolas Capens4b743732018-05-28 13:22:07 -0400971 reg = oC[i + dynamicAddress(src.rel)];
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500972 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400973 break;
974 case Shader::PARAMETER_DEPTHOUT:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500975 reg.x = oDepth;
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400976 break;
977 default:
978 ASSERT(false);
979 }
980
981 const Float4 &x = reg[(src.swizzle >> 0) & 0x3];
982 const Float4 &y = reg[(src.swizzle >> 2) & 0x3];
983 const Float4 &z = reg[(src.swizzle >> 4) & 0x3];
984 const Float4 &w = reg[(src.swizzle >> 6) & 0x3];
985
986 Vector4f mod;
987
988 switch(src.modifier)
989 {
990 case Shader::MODIFIER_NONE:
991 mod.x = x;
992 mod.y = y;
993 mod.z = z;
994 mod.w = w;
995 break;
996 case Shader::MODIFIER_NEGATE:
997 mod.x = -x;
998 mod.y = -y;
999 mod.z = -z;
1000 mod.w = -w;
1001 break;
1002 case Shader::MODIFIER_ABS:
1003 mod.x = Abs(x);
1004 mod.y = Abs(y);
1005 mod.z = Abs(z);
1006 mod.w = Abs(w);
1007 break;
1008 case Shader::MODIFIER_ABS_NEGATE:
1009 mod.x = -Abs(x);
1010 mod.y = -Abs(y);
1011 mod.z = -Abs(z);
1012 mod.w = -Abs(w);
1013 break;
1014 case Shader::MODIFIER_NOT:
1015 mod.x = As<Float4>(As<Int4>(x) ^ Int4(0xFFFFFFFF));
1016 mod.y = As<Float4>(As<Int4>(y) ^ Int4(0xFFFFFFFF));
1017 mod.z = As<Float4>(As<Int4>(z) ^ Int4(0xFFFFFFFF));
1018 mod.w = As<Float4>(As<Int4>(w) ^ Int4(0xFFFFFFFF));
1019 break;
1020 default:
1021 ASSERT(false);
1022 }
1023
1024 return mod;
1025 }
1026
Alexis Hetu2c2a7b22015-10-27 16:12:11 -04001027 RValue<Pointer<Byte>> PixelProgram::uniformAddress(int bufferIndex, unsigned int index)
1028 {
1029 if(bufferIndex == -1)
1030 {
1031 return data + OFFSET(DrawData, ps.c[index]);
1032 }
1033 else
1034 {
1035 return *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, ps.u[bufferIndex])) + index;
1036 }
1037 }
1038
1039 RValue<Pointer<Byte>> PixelProgram::uniformAddress(int bufferIndex, unsigned int index, Int& offset)
1040 {
1041 return uniformAddress(bufferIndex, index) + offset * sizeof(float4);
1042 }
1043
Nicolas Capens4f172c72016-01-13 08:34:30 -05001044 Vector4f PixelProgram::readConstant(const Src &src, unsigned int offset)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001045 {
1046 Vector4f c;
Nicolas Capens5d961882016-01-01 23:18:14 -05001047 unsigned int i = src.index + offset;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001048
1049 if(src.rel.type == Shader::PARAMETER_VOID) // Not relative
1050 {
Alexis Hetu2c2a7b22015-10-27 16:12:11 -04001051 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i));
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001052
1053 c.x = c.x.xxxx;
1054 c.y = c.y.yyyy;
1055 c.z = c.z.zzzz;
1056 c.w = c.w.wwww;
1057
1058 if(shader->containsDefineInstruction()) // Constant may be known at compile time
1059 {
1060 for(size_t j = 0; j < shader->getLength(); j++)
1061 {
1062 const Shader::Instruction &instruction = *shader->getInstruction(j);
1063
1064 if(instruction.opcode == Shader::OPCODE_DEF)
1065 {
1066 if(instruction.dst.index == i)
1067 {
1068 c.x = Float4(instruction.src[0].value[0]);
1069 c.y = Float4(instruction.src[0].value[1]);
1070 c.z = Float4(instruction.src[0].value[2]);
1071 c.w = Float4(instruction.src[0].value[3]);
1072
1073 break;
1074 }
1075 }
1076 }
1077 }
1078 }
Nicolas Capens4b743732018-05-28 13:22:07 -04001079 else if(!src.rel.dynamic || src.rel.type == Shader::PARAMETER_LOOP)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001080 {
Nicolas Capens4b743732018-05-28 13:22:07 -04001081 Int a = relativeAddress(src.rel, src.bufferIndex);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001082
Alexis Hetu2c2a7b22015-10-27 16:12:11 -04001083 c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, a));
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001084
1085 c.x = c.x.xxxx;
1086 c.y = c.y.yyyy;
1087 c.z = c.z.zzzz;
1088 c.w = c.w.wwww;
1089 }
Nicolas Capens4b743732018-05-28 13:22:07 -04001090 else
1091 {
1092 int component = src.rel.swizzle & 0x03;
1093 Float4 a;
1094
1095 switch(src.rel.type)
1096 {
1097 case Shader::PARAMETER_TEMP: a = r[src.rel.index][component]; break;
1098 case Shader::PARAMETER_INPUT: a = v[src.rel.index][component]; break;
1099 case Shader::PARAMETER_OUTPUT: a = oC[src.rel.index][component]; break;
1100 case Shader::PARAMETER_CONST: a = *Pointer<Float>(uniformAddress(src.bufferIndex, src.rel.index) + component * sizeof(float)); break;
1101 case Shader::PARAMETER_MISCTYPE:
1102 switch(src.rel.index)
1103 {
1104 case Shader::VPosIndex: a = vPos.x; break;
1105 case Shader::VFaceIndex: a = vFace.x; break;
1106 default: ASSERT(false);
1107 }
1108 break;
1109 default: ASSERT(false);
1110 }
1111
1112 Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
1113
1114 index = Min(As<UInt4>(index), UInt4(VERTEX_UNIFORM_VECTORS)); // Clamp to constant register range, c[VERTEX_UNIFORM_VECTORS] = {0, 0, 0, 0}
1115
1116 Int index0 = Extract(index, 0);
1117 Int index1 = Extract(index, 1);
1118 Int index2 = Extract(index, 2);
1119 Int index3 = Extract(index, 3);
1120
1121 c.x = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index0), 16);
1122 c.y = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index1), 16);
1123 c.z = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index2), 16);
1124 c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index3), 16);
1125
1126 transpose4x4(c.x, c.y, c.z, c.w);
1127 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001128
1129 return c;
1130 }
1131
Nicolas Capens4b743732018-05-28 13:22:07 -04001132 Int PixelProgram::relativeAddress(const Shader::Relative &rel, int bufferIndex)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001133 {
Nicolas Capens4b743732018-05-28 13:22:07 -04001134 ASSERT(!rel.dynamic);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001135
Nicolas Capens4b743732018-05-28 13:22:07 -04001136 if(rel.type == Shader::PARAMETER_TEMP)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001137 {
Nicolas Capens4b743732018-05-28 13:22:07 -04001138 return As<Int>(Extract(r[rel.index].x, 0)) * rel.scale;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001139 }
Nicolas Capens4b743732018-05-28 13:22:07 -04001140 else if(rel.type == Shader::PARAMETER_INPUT)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001141 {
Nicolas Capens4b743732018-05-28 13:22:07 -04001142 return As<Int>(Extract(v[rel.index].x, 0)) * rel.scale;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001143 }
Nicolas Capens4b743732018-05-28 13:22:07 -04001144 else if(rel.type == Shader::PARAMETER_OUTPUT)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001145 {
Nicolas Capens4b743732018-05-28 13:22:07 -04001146 return As<Int>(Extract(oC[rel.index].x, 0)) * rel.scale;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001147 }
Nicolas Capens4b743732018-05-28 13:22:07 -04001148 else if(rel.type == Shader::PARAMETER_CONST)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001149 {
Nicolas Capens4b743732018-05-28 13:22:07 -04001150 return *Pointer<Int>(uniformAddress(bufferIndex, rel.index)) * rel.scale;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001151 }
Nicolas Capens4b743732018-05-28 13:22:07 -04001152 else if(rel.type == Shader::PARAMETER_LOOP)
Nicolas Capens907700d2016-01-20 17:09:28 -05001153 {
1154 return aL[loopDepth];
1155 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001156 else ASSERT(false);
1157
1158 return 0;
1159 }
1160
Nicolas Capens4b743732018-05-28 13:22:07 -04001161 Int4 PixelProgram::dynamicAddress(const Shader::Relative &rel)
1162 {
1163 int component = rel.swizzle & 0x03;
1164 Float4 a;
1165
1166 switch(rel.type)
1167 {
1168 case Shader::PARAMETER_TEMP: a = r[rel.index][component]; break;
1169 case Shader::PARAMETER_INPUT: a = v[rel.index][component]; break;
1170 case Shader::PARAMETER_OUTPUT: a = oC[rel.index][component]; break;
1171 case Shader::PARAMETER_MISCTYPE:
1172 switch(rel.index)
1173 {
1174 case Shader::VPosIndex: a = vPos.x; break;
1175 case Shader::VFaceIndex: a = vFace.x; break;
1176 default: ASSERT(false);
1177 }
1178 break;
1179 default: ASSERT(false);
1180 }
1181
1182 return As<Int4>(a) * Int4(rel.scale);
1183 }
1184
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001185 Float4 PixelProgram::linearToSRGB(const Float4 &x) // Approximates x^(1.0/2.2)
1186 {
1187 Float4 sqrtx = Rcp_pp(RcpSqrt_pp(x));
1188 Float4 sRGB = sqrtx * Float4(1.14f) - x * Float4(0.14f);
1189
1190 return Min(Max(sRGB, Float4(0.0f)), Float4(1.0f));
1191 }
1192
Nicolas Capens4f172c72016-01-13 08:34:30 -05001193 void PixelProgram::M3X2(Vector4f &dst, Vector4f &src0, const Src &src1)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001194 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001195 Vector4f row0 = fetchRegister(src1, 0);
1196 Vector4f row1 = fetchRegister(src1, 1);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001197
1198 dst.x = dot3(src0, row0);
1199 dst.y = dot3(src0, row1);
1200 }
1201
Nicolas Capens4f172c72016-01-13 08:34:30 -05001202 void PixelProgram::M3X3(Vector4f &dst, Vector4f &src0, const Src &src1)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001203 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001204 Vector4f row0 = fetchRegister(src1, 0);
1205 Vector4f row1 = fetchRegister(src1, 1);
1206 Vector4f row2 = fetchRegister(src1, 2);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001207
1208 dst.x = dot3(src0, row0);
1209 dst.y = dot3(src0, row1);
1210 dst.z = dot3(src0, row2);
1211 }
1212
Nicolas Capens4f172c72016-01-13 08:34:30 -05001213 void PixelProgram::M3X4(Vector4f &dst, Vector4f &src0, const Src &src1)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001214 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001215 Vector4f row0 = fetchRegister(src1, 0);
1216 Vector4f row1 = fetchRegister(src1, 1);
1217 Vector4f row2 = fetchRegister(src1, 2);
1218 Vector4f row3 = fetchRegister(src1, 3);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001219
1220 dst.x = dot3(src0, row0);
1221 dst.y = dot3(src0, row1);
1222 dst.z = dot3(src0, row2);
1223 dst.w = dot3(src0, row3);
1224 }
1225
Nicolas Capens4f172c72016-01-13 08:34:30 -05001226 void PixelProgram::M4X3(Vector4f &dst, Vector4f &src0, const Src &src1)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001227 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001228 Vector4f row0 = fetchRegister(src1, 0);
1229 Vector4f row1 = fetchRegister(src1, 1);
1230 Vector4f row2 = fetchRegister(src1, 2);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001231
1232 dst.x = dot4(src0, row0);
1233 dst.y = dot4(src0, row1);
1234 dst.z = dot4(src0, row2);
1235 }
1236
Nicolas Capens4f172c72016-01-13 08:34:30 -05001237 void PixelProgram::M4X4(Vector4f &dst, Vector4f &src0, const Src &src1)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001238 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001239 Vector4f row0 = fetchRegister(src1, 0);
1240 Vector4f row1 = fetchRegister(src1, 1);
1241 Vector4f row2 = fetchRegister(src1, 2);
1242 Vector4f row3 = fetchRegister(src1, 3);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001243
1244 dst.x = dot4(src0, row0);
1245 dst.y = dot4(src0, row1);
1246 dst.z = dot4(src0, row2);
1247 dst.w = dot4(src0, row3);
1248 }
1249
Nicolas Capensa0b57832017-11-07 13:07:53 -05001250 void PixelProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1, bool project, bool bias)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001251 {
Nicolas Capens0484c792016-06-13 22:02:36 -04001252 if(project)
1253 {
1254 Vector4f proj;
1255 Float4 rw = reciprocal(src0.w);
1256 proj.x = src0.x * rw;
1257 proj.y = src0.y * rw;
1258 proj.z = src0.z * rw;
1259
Nicolas Capensa0b57832017-11-07 13:07:53 -05001260 dst = sampleTexture(src1, proj, src0.x, (src0), (src0), (src0), Implicit);
Nicolas Capens0484c792016-06-13 22:02:36 -04001261 }
1262 else
1263 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001264 dst = sampleTexture(src1, src0, src0.x, (src0), (src0), (src0), bias ? Bias : Implicit);
Nicolas Capens0484c792016-06-13 22:02:36 -04001265 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001266 }
1267
Nicolas Capensa0b57832017-11-07 13:07:53 -05001268 void PixelProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001269 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001270 dst = sampleTexture(src1, src0, (src0.x), (src0), (src0), offset, {Implicit, Offset});
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001271 }
1272
Nicolas Capensa0b57832017-11-07 13:07:53 -05001273 void PixelProgram::TEXLODOFFSET(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset, Float4 &lod)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001274 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001275 dst = sampleTexture(src1, src0, lod, (src0), (src0), offset, {Lod, Offset});
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001276 }
1277
Nicolas Capensa0b57832017-11-07 13:07:53 -05001278 void PixelProgram::TEXBIAS(Vector4f &dst, Vector4f &src0, const Src &src1, Float4 &bias)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001279 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001280 dst = sampleTexture(src1, src0, bias, (src0), (src0), (src0), Bias);
1281 }
Nicolas Capens67fdd832017-12-21 11:20:54 -05001282
Nicolas Capensa0b57832017-11-07 13:07:53 -05001283 void PixelProgram::TEXOFFSETBIAS(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset, Float4 &bias)
1284 {
1285 dst = sampleTexture(src1, src0, bias, (src0), (src0), offset, {Bias, Offset});
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001286 }
1287
Nicolas Capensa0b57832017-11-07 13:07:53 -05001288 void PixelProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Float4 &lod)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001289 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001290 dst = sampleTexture(src1, src0, lod, (src0), (src0), (src0), Fetch);
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001291 }
1292
Nicolas Capensa0b57832017-11-07 13:07:53 -05001293 void PixelProgram::TEXELFETCHOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &offset, Float4 &lod)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001294 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001295 dst = sampleTexture(src1, src0, lod, (src0), (src0), offset, {Fetch, Offset});
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001296 }
1297
Nicolas Capensa0b57832017-11-07 13:07:53 -05001298 void PixelProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &dsx, Vector4f &dsy)
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001299 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001300 dst = sampleTexture(src1, src0, (src0.x), dsx, dsy, (src0), Grad);
Alexis Hetu25d47fc2015-10-22 13:58:32 -04001301 }
1302
Nicolas Capensa0b57832017-11-07 13:07:53 -05001303 void PixelProgram::TEXGRADOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &dsx, Vector4f &dsy, Vector4f &offset)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001304 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001305 dst = sampleTexture(src1, src0, (src0.x), dsx, dsy, offset, {Grad, Offset});
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001306 }
1307
Nicolas Capensa0b57832017-11-07 13:07:53 -05001308 void PixelProgram::TEXLOD(Vector4f &dst, Vector4f &src0, const Src &src1, Float4 &lod)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001309 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001310 dst = sampleTexture(src1, src0, lod, (src0), (src0), (src0), Lod);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001311 }
1312
Nicolas Capens4f172c72016-01-13 08:34:30 -05001313 void PixelProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
Alexis Hetu9bcb31d2015-07-22 17:03:26 -04001314 {
Nicolas Capens79d0e562018-11-27 17:07:49 -05001315 bool uniformSampler = (src1.type == Shader::PARAMETER_SAMPLER && src1.rel.type == Shader::PARAMETER_VOID);
Nicolas Capensa9727582018-11-28 17:33:24 -05001316 Int offset = uniformSampler ? src1.index * sizeof(Texture) : As<Int>(Float(fetchRegister(src1).x.x)) * sizeof(Texture);
1317 Pointer<Byte> texture = data + OFFSET(DrawData, mipmap) + offset;
Nicolas Capens79d0e562018-11-27 17:07:49 -05001318
Nicolas Capens89a218b2017-11-07 13:05:20 -05001319 dst = SamplerCore::textureSize(texture, lod);
Alexis Hetu9bcb31d2015-07-22 17:03:26 -04001320 }
1321
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001322 void PixelProgram::TEXKILL(Int cMask[4], Vector4f &src, unsigned char mask)
1323 {
1324 Int kill = -1;
1325
1326 if(mask & 0x1) kill &= SignMask(CmpNLT(src.x, Float4(0.0f)));
1327 if(mask & 0x2) kill &= SignMask(CmpNLT(src.y, Float4(0.0f)));
1328 if(mask & 0x4) kill &= SignMask(CmpNLT(src.z, Float4(0.0f)));
1329 if(mask & 0x8) kill &= SignMask(CmpNLT(src.w, Float4(0.0f)));
1330
1331 // FIXME: Dynamic branching affects TEXKILL?
1332 // if(shader->containsDynamicBranching())
1333 // {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001334 // kill = ~SignMask(enableMask());
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001335 // }
1336
1337 for(unsigned int q = 0; q < state.multiSample; q++)
1338 {
1339 cMask[q] &= kill;
1340 }
1341
1342 // FIXME: Branch to end of shader if all killed?
1343 }
1344
Nicolas Capens4f172c72016-01-13 08:34:30 -05001345 void PixelProgram::DISCARD(Int cMask[4], const Shader::Instruction *instruction)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001346 {
1347 Int kill = 0;
1348
1349 if(shader->containsDynamicBranching())
1350 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001351 kill = ~SignMask(enableMask(instruction));
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001352 }
1353
1354 for(unsigned int q = 0; q < state.multiSample; q++)
1355 {
1356 cMask[q] &= kill;
1357 }
1358
1359 // FIXME: Branch to end of shader if all killed?
1360 }
1361
1362 void PixelProgram::DFDX(Vector4f &dst, Vector4f &src)
1363 {
1364 dst.x = src.x.yyww - src.x.xxzz;
1365 dst.y = src.y.yyww - src.y.xxzz;
1366 dst.z = src.z.yyww - src.z.xxzz;
1367 dst.w = src.w.yyww - src.w.xxzz;
1368 }
1369
1370 void PixelProgram::DFDY(Vector4f &dst, Vector4f &src)
1371 {
1372 dst.x = src.x.zwzw - src.x.xyxy;
1373 dst.y = src.y.zwzw - src.y.xyxy;
1374 dst.z = src.z.zwzw - src.z.xyxy;
1375 dst.w = src.w.zwzw - src.w.xyxy;
1376 }
1377
1378 void PixelProgram::FWIDTH(Vector4f &dst, Vector4f &src)
1379 {
1380 // abs(dFdx(src)) + abs(dFdy(src));
1381 dst.x = Abs(src.x.yyww - src.x.xxzz) + Abs(src.x.zwzw - src.x.xyxy);
1382 dst.y = Abs(src.y.yyww - src.y.xxzz) + Abs(src.y.zwzw - src.y.xyxy);
1383 dst.z = Abs(src.z.yyww - src.z.xxzz) + Abs(src.z.zwzw - src.z.xyxy);
1384 dst.w = Abs(src.w.yyww - src.w.xxzz) + Abs(src.w.zwzw - src.w.xyxy);
1385 }
1386
Nicolas Capens4f172c72016-01-13 08:34:30 -05001387 void PixelProgram::BREAK()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001388 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001389 enableBreak = enableBreak & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001390 }
1391
Nicolas Capens4f172c72016-01-13 08:34:30 -05001392 void PixelProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001393 {
1394 Int4 condition;
1395
1396 switch(control)
1397 {
1398 case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
1399 case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x); break;
1400 case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
1401 case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x); break;
1402 case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
1403 case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x); break;
1404 default:
1405 ASSERT(false);
1406 }
1407
Nicolas Capens4f172c72016-01-13 08:34:30 -05001408 BREAK(condition);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001409 }
1410
Nicolas Capens4f172c72016-01-13 08:34:30 -05001411 void PixelProgram::BREAKP(const Src &predicateRegister) // FIXME: Factor out parts common with BREAKC
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001412 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001413 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001414
1415 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1416 {
1417 condition = ~condition;
1418 }
1419
Nicolas Capens4f172c72016-01-13 08:34:30 -05001420 BREAK(condition);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001421 }
1422
Nicolas Capens4f172c72016-01-13 08:34:30 -05001423 void PixelProgram::BREAK(Int4 &condition)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001424 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001425 condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001426
Nicolas Capens4f172c72016-01-13 08:34:30 -05001427 enableBreak = enableBreak & ~condition;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001428 }
1429
Nicolas Capens4f172c72016-01-13 08:34:30 -05001430 void PixelProgram::CONTINUE()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001431 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001432 enableContinue = enableContinue & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001433 }
1434
1435 void PixelProgram::TEST()
1436 {
Nicolas Capens2f490f02018-11-01 16:53:36 -04001437 enableContinue = restoreContinue.back();
1438 restoreContinue.pop_back();
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001439 }
1440
Nicolas Capens6e8ec332018-11-06 11:56:21 -05001441 void PixelProgram::SCALAR()
1442 {
1443 scalar = true;
1444 }
1445
Nicolas Capens4f172c72016-01-13 08:34:30 -05001446 void PixelProgram::CALL(int labelIndex, int callSiteIndex)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001447 {
1448 if(!labelBlock[labelIndex])
1449 {
1450 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1451 }
1452
1453 if(callRetBlock[labelIndex].size() > 1)
1454 {
Nicolas Capens0f34a982019-02-11 16:02:23 -05001455 callStack[stackIndex++] = UInt(callSiteIndex);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001456 }
1457
Nicolas Capens4f172c72016-01-13 08:34:30 -05001458 Int4 restoreLeave = enableLeave;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001459
1460 Nucleus::createBr(labelBlock[labelIndex]);
1461 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1462
Nicolas Capens4f172c72016-01-13 08:34:30 -05001463 enableLeave = restoreLeave;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001464 }
1465
Nicolas Capens4f172c72016-01-13 08:34:30 -05001466 void PixelProgram::CALLNZ(int labelIndex, int callSiteIndex, const Src &src)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001467 {
1468 if(src.type == Shader::PARAMETER_CONSTBOOL)
1469 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001470 CALLNZb(labelIndex, callSiteIndex, src);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001471 }
1472 else if(src.type == Shader::PARAMETER_PREDICATE)
1473 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001474 CALLNZp(labelIndex, callSiteIndex, src);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001475 }
1476 else ASSERT(false);
1477 }
1478
Nicolas Capens4f172c72016-01-13 08:34:30 -05001479 void PixelProgram::CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001480 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001481 Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData, ps.b[boolRegister.index])) != Byte(0)); // FIXME
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001482
1483 if(boolRegister.modifier == Shader::MODIFIER_NOT)
1484 {
1485 condition = !condition;
1486 }
1487
1488 if(!labelBlock[labelIndex])
1489 {
1490 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1491 }
1492
1493 if(callRetBlock[labelIndex].size() > 1)
1494 {
Nicolas Capens0f34a982019-02-11 16:02:23 -05001495 callStack[stackIndex++] = UInt(callSiteIndex);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001496 }
1497
Nicolas Capens4f172c72016-01-13 08:34:30 -05001498 Int4 restoreLeave = enableLeave;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001499
1500 branch(condition, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
1501 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1502
Nicolas Capens4f172c72016-01-13 08:34:30 -05001503 enableLeave = restoreLeave;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001504 }
1505
Nicolas Capens4f172c72016-01-13 08:34:30 -05001506 void PixelProgram::CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001507 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001508 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001509
1510 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1511 {
1512 condition = ~condition;
1513 }
1514
Alexis Hetu48d47a42019-01-10 14:04:26 -05001515 condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001516
1517 if(!labelBlock[labelIndex])
1518 {
1519 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1520 }
1521
1522 if(callRetBlock[labelIndex].size() > 1)
1523 {
Nicolas Capens0f34a982019-02-11 16:02:23 -05001524 callStack[stackIndex++] = UInt(callSiteIndex);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001525 }
1526
Nicolas Capens4f172c72016-01-13 08:34:30 -05001527 enableIndex++;
Alexis Hetu48d47a42019-01-10 14:04:26 -05001528 enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001529 Int4 restoreLeave = enableLeave;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001530
1531 Bool notAllFalse = SignMask(condition) != 0;
1532 branch(notAllFalse, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
1533 Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
1534
Nicolas Capens4f172c72016-01-13 08:34:30 -05001535 enableIndex--;
1536 enableLeave = restoreLeave;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001537 }
1538
Nicolas Capens4f172c72016-01-13 08:34:30 -05001539 void PixelProgram::ELSE()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001540 {
1541 ifDepth--;
1542
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001543 BasicBlock *falseBlock = ifFalseBlock[ifDepth];
1544 BasicBlock *endBlock = Nucleus::createBasicBlock();
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001545
1546 if(isConditionalIf[ifDepth])
1547 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001548 Int4 condition = ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] & enableStack[Min(enableIndex - 1, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001549 Bool notAllFalse = SignMask(condition) != 0;
1550
1551 branch(notAllFalse, falseBlock, endBlock);
1552
Alexis Hetu48d47a42019-01-10 14:04:26 -05001553 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))];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001554 }
1555 else
1556 {
1557 Nucleus::createBr(endBlock);
1558 Nucleus::setInsertBlock(falseBlock);
1559 }
1560
1561 ifFalseBlock[ifDepth] = endBlock;
1562
1563 ifDepth++;
1564 }
1565
Nicolas Capens4f172c72016-01-13 08:34:30 -05001566 void PixelProgram::ENDIF()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001567 {
1568 ifDepth--;
1569
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001570 BasicBlock *endBlock = ifFalseBlock[ifDepth];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001571
1572 Nucleus::createBr(endBlock);
1573 Nucleus::setInsertBlock(endBlock);
1574
1575 if(isConditionalIf[ifDepth])
1576 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001577 enableIndex--;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001578 }
1579 }
1580
Nicolas Capens4f172c72016-01-13 08:34:30 -05001581 void PixelProgram::ENDLOOP()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001582 {
1583 loopRepDepth--;
1584
Nicolas Capens4f172c72016-01-13 08:34:30 -05001585 aL[loopDepth] = aL[loopDepth] + increment[loopDepth]; // FIXME: +=
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001586
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001587 BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1588 BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001589
1590 Nucleus::createBr(testBlock);
1591 Nucleus::setInsertBlock(endBlock);
1592
Nicolas Capens4f172c72016-01-13 08:34:30 -05001593 loopDepth--;
1594 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001595 }
1596
Nicolas Capens4f172c72016-01-13 08:34:30 -05001597 void PixelProgram::ENDREP()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001598 {
1599 loopRepDepth--;
1600
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001601 BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1602 BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001603
1604 Nucleus::createBr(testBlock);
1605 Nucleus::setInsertBlock(endBlock);
1606
Nicolas Capens4f172c72016-01-13 08:34:30 -05001607 loopDepth--;
1608 enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001609 }
1610
Nicolas Capens4f172c72016-01-13 08:34:30 -05001611 void PixelProgram::ENDWHILE()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001612 {
1613 loopRepDepth--;
1614
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001615 BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
1616 BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001617
1618 Nucleus::createBr(testBlock);
1619 Nucleus::setInsertBlock(endBlock);
1620
Nicolas Capens4f172c72016-01-13 08:34:30 -05001621 enableIndex--;
Nicolas Capens6e8ec332018-11-06 11:56:21 -05001622 scalar = false;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001623 }
1624
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001625 void PixelProgram::ENDSWITCH()
1626 {
1627 loopRepDepth--;
1628
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001629 BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001630
Nicolas Capensac6d5052018-01-05 15:34:00 -05001631 Nucleus::createBr(endBlock);
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001632 Nucleus::setInsertBlock(endBlock);
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001633 }
1634
Nicolas Capens4f172c72016-01-13 08:34:30 -05001635 void PixelProgram::IF(const Src &src)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001636 {
1637 if(src.type == Shader::PARAMETER_CONSTBOOL)
1638 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001639 IFb(src);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001640 }
1641 else if(src.type == Shader::PARAMETER_PREDICATE)
1642 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001643 IFp(src);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001644 }
1645 else
1646 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001647 Int4 condition = As<Int4>(fetchRegister(src).x);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001648 IF(condition);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001649 }
1650 }
1651
Nicolas Capens4f172c72016-01-13 08:34:30 -05001652 void PixelProgram::IFb(const Src &boolRegister)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001653 {
1654 ASSERT(ifDepth < 24 + 4);
1655
Nicolas Capens4f172c72016-01-13 08:34:30 -05001656 Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData, ps.b[boolRegister.index])) != Byte(0)); // FIXME
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001657
1658 if(boolRegister.modifier == Shader::MODIFIER_NOT)
1659 {
1660 condition = !condition;
1661 }
1662
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001663 BasicBlock *trueBlock = Nucleus::createBasicBlock();
1664 BasicBlock *falseBlock = Nucleus::createBasicBlock();
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001665
1666 branch(condition, trueBlock, falseBlock);
1667
1668 isConditionalIf[ifDepth] = false;
1669 ifFalseBlock[ifDepth] = falseBlock;
1670
1671 ifDepth++;
1672 }
1673
Nicolas Capens4f172c72016-01-13 08:34:30 -05001674 void PixelProgram::IFp(const Src &predicateRegister)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001675 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001676 Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001677
1678 if(predicateRegister.modifier == Shader::MODIFIER_NOT)
1679 {
1680 condition = ~condition;
1681 }
1682
Nicolas Capens4f172c72016-01-13 08:34:30 -05001683 IF(condition);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001684 }
1685
Nicolas Capens4f172c72016-01-13 08:34:30 -05001686 void PixelProgram::IFC(Vector4f &src0, Vector4f &src1, Control control)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001687 {
1688 Int4 condition;
1689
1690 switch(control)
1691 {
1692 case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
1693 case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x); break;
1694 case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
1695 case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x); break;
1696 case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
1697 case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x); break;
1698 default:
1699 ASSERT(false);
1700 }
1701
Nicolas Capens4f172c72016-01-13 08:34:30 -05001702 IF(condition);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001703 }
1704
Nicolas Capens4f172c72016-01-13 08:34:30 -05001705 void PixelProgram::IF(Int4 &condition)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001706 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001707 condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001708
Nicolas Capens4f172c72016-01-13 08:34:30 -05001709 enableIndex++;
Alexis Hetu48d47a42019-01-10 14:04:26 -05001710 enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001711
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001712 BasicBlock *trueBlock = Nucleus::createBasicBlock();
1713 BasicBlock *falseBlock = Nucleus::createBasicBlock();
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001714
1715 Bool notAllFalse = SignMask(condition) != 0;
1716
1717 branch(notAllFalse, trueBlock, falseBlock);
1718
1719 isConditionalIf[ifDepth] = true;
1720 ifFalseBlock[ifDepth] = falseBlock;
1721
1722 ifDepth++;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001723 }
1724
1725 void PixelProgram::LABEL(int labelIndex)
1726 {
1727 if(!labelBlock[labelIndex])
1728 {
1729 labelBlock[labelIndex] = Nucleus::createBasicBlock();
1730 }
1731
1732 Nucleus::setInsertBlock(labelBlock[labelIndex]);
1733 currentLabel = labelIndex;
1734 }
1735
Nicolas Capens4f172c72016-01-13 08:34:30 -05001736 void PixelProgram::LOOP(const Src &integerRegister)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001737 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001738 loopDepth++;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001739
Nicolas Capens4f172c72016-01-13 08:34:30 -05001740 iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData, ps.i[integerRegister.index][0]));
1741 aL[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData, ps.i[integerRegister.index][1]));
1742 increment[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData, ps.i[integerRegister.index][2]));
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001743
Nicolas Capens4f172c72016-01-13 08:34:30 -05001744 // If(increment[loopDepth] == 0)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001745 // {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001746 // increment[loopDepth] = 1;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001747 // }
1748
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001749 BasicBlock *loopBlock = Nucleus::createBasicBlock();
1750 BasicBlock *testBlock = Nucleus::createBasicBlock();
1751 BasicBlock *endBlock = Nucleus::createBasicBlock();
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001752
1753 loopRepTestBlock[loopRepDepth] = testBlock;
1754 loopRepEndBlock[loopRepDepth] = endBlock;
1755
1756 // FIXME: jump(testBlock)
1757 Nucleus::createBr(testBlock);
1758 Nucleus::setInsertBlock(testBlock);
1759
Nicolas Capens4f172c72016-01-13 08:34:30 -05001760 branch(iteration[loopDepth] > 0, loopBlock, endBlock);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001761 Nucleus::setInsertBlock(loopBlock);
1762
Nicolas Capens4f172c72016-01-13 08:34:30 -05001763 iteration[loopDepth] = iteration[loopDepth] - 1; // FIXME: --
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001764
1765 loopRepDepth++;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001766 }
1767
Nicolas Capens4f172c72016-01-13 08:34:30 -05001768 void PixelProgram::REP(const Src &integerRegister)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001769 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001770 loopDepth++;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001771
Nicolas Capens4f172c72016-01-13 08:34:30 -05001772 iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData, ps.i[integerRegister.index][0]));
1773 aL[loopDepth] = aL[loopDepth - 1];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001774
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001775 BasicBlock *loopBlock = Nucleus::createBasicBlock();
1776 BasicBlock *testBlock = Nucleus::createBasicBlock();
1777 BasicBlock *endBlock = Nucleus::createBasicBlock();
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001778
1779 loopRepTestBlock[loopRepDepth] = testBlock;
1780 loopRepEndBlock[loopRepDepth] = endBlock;
1781
1782 // FIXME: jump(testBlock)
1783 Nucleus::createBr(testBlock);
1784 Nucleus::setInsertBlock(testBlock);
1785
Nicolas Capens4f172c72016-01-13 08:34:30 -05001786 branch(iteration[loopDepth] > 0, loopBlock, endBlock);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001787 Nucleus::setInsertBlock(loopBlock);
1788
Nicolas Capens4f172c72016-01-13 08:34:30 -05001789 iteration[loopDepth] = iteration[loopDepth] - 1; // FIXME: --
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001790
1791 loopRepDepth++;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001792 }
1793
Nicolas Capens4f172c72016-01-13 08:34:30 -05001794 void PixelProgram::WHILE(const Src &temporaryRegister)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001795 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001796 enableIndex++;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001797
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001798 BasicBlock *loopBlock = Nucleus::createBasicBlock();
1799 BasicBlock *testBlock = Nucleus::createBasicBlock();
1800 BasicBlock *endBlock = Nucleus::createBasicBlock();
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001801
1802 loopRepTestBlock[loopRepDepth] = testBlock;
1803 loopRepEndBlock[loopRepDepth] = endBlock;
1804
Nicolas Capens4f172c72016-01-13 08:34:30 -05001805 Int4 restoreBreak = enableBreak;
Nicolas Capens2f490f02018-11-01 16:53:36 -04001806 restoreContinue.push_back(enableContinue);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001807
Nicolas Capensd6bcc112018-01-08 14:09:51 -05001808 // TODO: jump(testBlock)
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001809 Nucleus::createBr(testBlock);
1810 Nucleus::setInsertBlock(testBlock);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001811
Nicolas Capensc2534f42016-04-04 11:13:24 -04001812 const Vector4f &src = fetchRegister(temporaryRegister);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001813 Int4 condition = As<Int4>(src.x);
Alexis Hetu48d47a42019-01-10 14:04:26 -05001814 condition &= enableStack[Min(enableIndex - 1, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Nicolas Capens2ff29482016-04-28 15:28:02 -04001815 if(shader->containsLeaveInstruction()) condition &= enableLeave;
Nicolas Capens6d123312018-01-08 12:57:52 -05001816 if(shader->containsBreakInstruction()) condition &= enableBreak;
Alexis Hetu48d47a42019-01-10 14:04:26 -05001817 enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001818
1819 Bool notAllFalse = SignMask(condition) != 0;
1820 branch(notAllFalse, loopBlock, endBlock);
1821
1822 Nucleus::setInsertBlock(endBlock);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001823 enableBreak = restoreBreak;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001824
1825 Nucleus::setInsertBlock(loopBlock);
1826
1827 loopRepDepth++;
Nicolas Capens6e8ec332018-11-06 11:56:21 -05001828 scalar = false;
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001829 }
1830
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001831 void PixelProgram::SWITCH()
1832 {
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001833 BasicBlock *endBlock = Nucleus::createBasicBlock();
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001834
1835 loopRepTestBlock[loopRepDepth] = nullptr;
1836 loopRepEndBlock[loopRepDepth] = endBlock;
1837
Nicolas Capensd6bcc112018-01-08 14:09:51 -05001838 Int4 restoreBreak = enableBreak;
1839
1840 BasicBlock *currentBlock = Nucleus::getInsertBlock();
1841
1842 Nucleus::setInsertBlock(endBlock);
1843 enableBreak = restoreBreak;
1844
1845 Nucleus::setInsertBlock(currentBlock);
1846
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001847 loopRepDepth++;
Alexis Hetu9aa83a92016-05-02 17:34:46 -04001848 }
1849
Nicolas Capens4f172c72016-01-13 08:34:30 -05001850 void PixelProgram::RET()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001851 {
1852 if(currentLabel == -1)
1853 {
1854 returnBlock = Nucleus::createBasicBlock();
1855 Nucleus::createBr(returnBlock);
1856 }
1857 else
1858 {
Nicolas Capensc8b67a42016-09-25 15:02:52 -04001859 BasicBlock *unreachableBlock = Nucleus::createBasicBlock();
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001860
1861 if(callRetBlock[currentLabel].size() > 1) // Pop the return destination from the call stack
1862 {
1863 // FIXME: Encapsulate
Nicolas Capens4f172c72016-01-13 08:34:30 -05001864 UInt index = callStack[--stackIndex];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001865
Nicolas Capens19336542016-09-26 10:32:29 -04001866 Value *value = index.loadValue();
Nicolas Capensb98fe5c2016-11-09 12:24:06 -05001867 SwitchCases *switchCases = Nucleus::createSwitch(value, unreachableBlock, (int)callRetBlock[currentLabel].size());
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001868
1869 for(unsigned int i = 0; i < callRetBlock[currentLabel].size(); i++)
1870 {
Nicolas Capensb98fe5c2016-11-09 12:24:06 -05001871 Nucleus::addSwitchCase(switchCases, i, callRetBlock[currentLabel][i]);
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001872 }
1873 }
1874 else if(callRetBlock[currentLabel].size() == 1) // Jump directly to the unique return destination
1875 {
1876 Nucleus::createBr(callRetBlock[currentLabel][0]);
1877 }
1878 else // Function isn't called
1879 {
1880 Nucleus::createBr(unreachableBlock);
1881 }
1882
1883 Nucleus::setInsertBlock(unreachableBlock);
1884 Nucleus::createUnreachable();
1885 }
1886 }
1887
Nicolas Capens4f172c72016-01-13 08:34:30 -05001888 void PixelProgram::LEAVE()
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001889 {
Alexis Hetu48d47a42019-01-10 14:04:26 -05001890 enableLeave = enableLeave & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001891
1892 // FIXME: Return from function if all instances left
1893 // FIXME: Use enableLeave in other control-flow constructs
1894 }
Nicolas Capens5d961882016-01-01 23:18:14 -05001895}