xref: /aosp_15_r20/external/swiftshader/src/Pipeline/SpirvShaderGLSLstd450.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "SpirvShader.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "ShaderCore.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "Device/Primitive.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "Pipeline/Constants.hpp"
20*03ce13f7SAndroid Build Coastguard Worker 
21*03ce13f7SAndroid Build Coastguard Worker #include <spirv/unified1/GLSL.std.450.h>
22*03ce13f7SAndroid Build Coastguard Worker #include <spirv/unified1/spirv.hpp>
23*03ce13f7SAndroid Build Coastguard Worker 
24*03ce13f7SAndroid Build Coastguard Worker namespace sw {
25*03ce13f7SAndroid Build Coastguard Worker 
26*03ce13f7SAndroid Build Coastguard Worker static constexpr float PI = 3.141592653589793f;
27*03ce13f7SAndroid Build Coastguard Worker 
EmitExtGLSLstd450(Spirv::InsnIterator insn)28*03ce13f7SAndroid Build Coastguard Worker void SpirvEmitter::EmitExtGLSLstd450(Spirv::InsnIterator insn)
29*03ce13f7SAndroid Build Coastguard Worker {
30*03ce13f7SAndroid Build Coastguard Worker 	auto &type = shader.getType(insn.resultTypeId());
31*03ce13f7SAndroid Build Coastguard Worker 	auto &dst = createIntermediate(insn.resultId(), type.componentCount);
32*03ce13f7SAndroid Build Coastguard Worker 	auto extInstIndex = static_cast<GLSLstd450>(insn.word(4));
33*03ce13f7SAndroid Build Coastguard Worker 
34*03ce13f7SAndroid Build Coastguard Worker 	switch(extInstIndex)
35*03ce13f7SAndroid Build Coastguard Worker 	{
36*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FAbs:
37*03ce13f7SAndroid Build Coastguard Worker 		{
38*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
39*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
40*03ce13f7SAndroid Build Coastguard Worker 			{
41*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Abs(src.Float(i)));
42*03ce13f7SAndroid Build Coastguard Worker 			}
43*03ce13f7SAndroid Build Coastguard Worker 		}
44*03ce13f7SAndroid Build Coastguard Worker 		break;
45*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450SAbs:
46*03ce13f7SAndroid Build Coastguard Worker 		{
47*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
48*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
49*03ce13f7SAndroid Build Coastguard Worker 			{
50*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Abs(src.Int(i)));
51*03ce13f7SAndroid Build Coastguard Worker 			}
52*03ce13f7SAndroid Build Coastguard Worker 		}
53*03ce13f7SAndroid Build Coastguard Worker 		break;
54*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Cross:
55*03ce13f7SAndroid Build Coastguard Worker 		{
56*03ce13f7SAndroid Build Coastguard Worker 			auto lhs = Operand(shader, *this, insn.word(5));
57*03ce13f7SAndroid Build Coastguard Worker 			auto rhs = Operand(shader, *this, insn.word(6));
58*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, lhs.Float(1) * rhs.Float(2) - rhs.Float(1) * lhs.Float(2));
59*03ce13f7SAndroid Build Coastguard Worker 			dst.move(1, lhs.Float(2) * rhs.Float(0) - rhs.Float(2) * lhs.Float(0));
60*03ce13f7SAndroid Build Coastguard Worker 			dst.move(2, lhs.Float(0) * rhs.Float(1) - rhs.Float(0) * lhs.Float(1));
61*03ce13f7SAndroid Build Coastguard Worker 		}
62*03ce13f7SAndroid Build Coastguard Worker 		break;
63*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Floor:
64*03ce13f7SAndroid Build Coastguard Worker 		{
65*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
66*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
67*03ce13f7SAndroid Build Coastguard Worker 			{
68*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Floor(src.Float(i)));
69*03ce13f7SAndroid Build Coastguard Worker 			}
70*03ce13f7SAndroid Build Coastguard Worker 		}
71*03ce13f7SAndroid Build Coastguard Worker 		break;
72*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Trunc:
73*03ce13f7SAndroid Build Coastguard Worker 		{
74*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
75*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
76*03ce13f7SAndroid Build Coastguard Worker 			{
77*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Trunc(src.Float(i)));
78*03ce13f7SAndroid Build Coastguard Worker 			}
79*03ce13f7SAndroid Build Coastguard Worker 		}
80*03ce13f7SAndroid Build Coastguard Worker 		break;
81*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Ceil:
82*03ce13f7SAndroid Build Coastguard Worker 		{
83*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
84*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
85*03ce13f7SAndroid Build Coastguard Worker 			{
86*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Ceil(src.Float(i)));
87*03ce13f7SAndroid Build Coastguard Worker 			}
88*03ce13f7SAndroid Build Coastguard Worker 		}
89*03ce13f7SAndroid Build Coastguard Worker 		break;
90*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Fract:
91*03ce13f7SAndroid Build Coastguard Worker 		{
92*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
93*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
94*03ce13f7SAndroid Build Coastguard Worker 			{
95*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Frac(src.Float(i)));
96*03ce13f7SAndroid Build Coastguard Worker 			}
97*03ce13f7SAndroid Build Coastguard Worker 		}
98*03ce13f7SAndroid Build Coastguard Worker 		break;
99*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Round:
100*03ce13f7SAndroid Build Coastguard Worker 		{
101*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
102*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
103*03ce13f7SAndroid Build Coastguard Worker 			{
104*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Round(src.Float(i)));
105*03ce13f7SAndroid Build Coastguard Worker 			}
106*03ce13f7SAndroid Build Coastguard Worker 		}
107*03ce13f7SAndroid Build Coastguard Worker 		break;
108*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450RoundEven:
109*03ce13f7SAndroid Build Coastguard Worker 		{
110*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
111*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
112*03ce13f7SAndroid Build Coastguard Worker 			{
113*03ce13f7SAndroid Build Coastguard Worker 				auto x = Round(src.Float(i));
114*03ce13f7SAndroid Build Coastguard Worker 				// dst = round(src) + ((round(src) < src) * 2 - 1) * (fract(src) == 0.5) * isOdd(round(src));
115*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, x + ((SIMD::Float(CmpLT(x, src.Float(i)) & SIMD::Int(1)) * SIMD::Float(2.0f)) - SIMD::Float(1.0f)) *
116*03ce13f7SAndroid Build Coastguard Worker 				                    SIMD::Float(CmpEQ(Frac(src.Float(i)), SIMD::Float(0.5f)) & SIMD::Int(1)) * SIMD::Float(SIMD::Int(x) & SIMD::Int(1)));
117*03ce13f7SAndroid Build Coastguard Worker 			}
118*03ce13f7SAndroid Build Coastguard Worker 		}
119*03ce13f7SAndroid Build Coastguard Worker 		break;
120*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FMin:
121*03ce13f7SAndroid Build Coastguard Worker 		{
122*03ce13f7SAndroid Build Coastguard Worker 			auto lhs = Operand(shader, *this, insn.word(5));
123*03ce13f7SAndroid Build Coastguard Worker 			auto rhs = Operand(shader, *this, insn.word(6));
124*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
125*03ce13f7SAndroid Build Coastguard Worker 			{
126*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Min(lhs.Float(i), rhs.Float(i)));
127*03ce13f7SAndroid Build Coastguard Worker 			}
128*03ce13f7SAndroid Build Coastguard Worker 		}
129*03ce13f7SAndroid Build Coastguard Worker 		break;
130*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FMax:
131*03ce13f7SAndroid Build Coastguard Worker 		{
132*03ce13f7SAndroid Build Coastguard Worker 			auto lhs = Operand(shader, *this, insn.word(5));
133*03ce13f7SAndroid Build Coastguard Worker 			auto rhs = Operand(shader, *this, insn.word(6));
134*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
135*03ce13f7SAndroid Build Coastguard Worker 			{
136*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Max(lhs.Float(i), rhs.Float(i)));
137*03ce13f7SAndroid Build Coastguard Worker 			}
138*03ce13f7SAndroid Build Coastguard Worker 		}
139*03ce13f7SAndroid Build Coastguard Worker 		break;
140*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450SMin:
141*03ce13f7SAndroid Build Coastguard Worker 		{
142*03ce13f7SAndroid Build Coastguard Worker 			auto lhs = Operand(shader, *this, insn.word(5));
143*03ce13f7SAndroid Build Coastguard Worker 			auto rhs = Operand(shader, *this, insn.word(6));
144*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
145*03ce13f7SAndroid Build Coastguard Worker 			{
146*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Min(lhs.Int(i), rhs.Int(i)));
147*03ce13f7SAndroid Build Coastguard Worker 			}
148*03ce13f7SAndroid Build Coastguard Worker 		}
149*03ce13f7SAndroid Build Coastguard Worker 		break;
150*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450SMax:
151*03ce13f7SAndroid Build Coastguard Worker 		{
152*03ce13f7SAndroid Build Coastguard Worker 			auto lhs = Operand(shader, *this, insn.word(5));
153*03ce13f7SAndroid Build Coastguard Worker 			auto rhs = Operand(shader, *this, insn.word(6));
154*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
155*03ce13f7SAndroid Build Coastguard Worker 			{
156*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Max(lhs.Int(i), rhs.Int(i)));
157*03ce13f7SAndroid Build Coastguard Worker 			}
158*03ce13f7SAndroid Build Coastguard Worker 		}
159*03ce13f7SAndroid Build Coastguard Worker 		break;
160*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UMin:
161*03ce13f7SAndroid Build Coastguard Worker 		{
162*03ce13f7SAndroid Build Coastguard Worker 			auto lhs = Operand(shader, *this, insn.word(5));
163*03ce13f7SAndroid Build Coastguard Worker 			auto rhs = Operand(shader, *this, insn.word(6));
164*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
165*03ce13f7SAndroid Build Coastguard Worker 			{
166*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Min(lhs.UInt(i), rhs.UInt(i)));
167*03ce13f7SAndroid Build Coastguard Worker 			}
168*03ce13f7SAndroid Build Coastguard Worker 		}
169*03ce13f7SAndroid Build Coastguard Worker 		break;
170*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UMax:
171*03ce13f7SAndroid Build Coastguard Worker 		{
172*03ce13f7SAndroid Build Coastguard Worker 			auto lhs = Operand(shader, *this, insn.word(5));
173*03ce13f7SAndroid Build Coastguard Worker 			auto rhs = Operand(shader, *this, insn.word(6));
174*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
175*03ce13f7SAndroid Build Coastguard Worker 			{
176*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Max(lhs.UInt(i), rhs.UInt(i)));
177*03ce13f7SAndroid Build Coastguard Worker 			}
178*03ce13f7SAndroid Build Coastguard Worker 		}
179*03ce13f7SAndroid Build Coastguard Worker 		break;
180*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Step:
181*03ce13f7SAndroid Build Coastguard Worker 		{
182*03ce13f7SAndroid Build Coastguard Worker 			auto edge = Operand(shader, *this, insn.word(5));
183*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(6));
184*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
185*03ce13f7SAndroid Build Coastguard Worker 			{
186*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, CmpNLT(x.Float(i), edge.Float(i)) & As<SIMD::Int>(SIMD::Float(1.0f)));
187*03ce13f7SAndroid Build Coastguard Worker 			}
188*03ce13f7SAndroid Build Coastguard Worker 		}
189*03ce13f7SAndroid Build Coastguard Worker 		break;
190*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450SmoothStep:
191*03ce13f7SAndroid Build Coastguard Worker 		{
192*03ce13f7SAndroid Build Coastguard Worker 			auto edge0 = Operand(shader, *this, insn.word(5));
193*03ce13f7SAndroid Build Coastguard Worker 			auto edge1 = Operand(shader, *this, insn.word(6));
194*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(7));
195*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
196*03ce13f7SAndroid Build Coastguard Worker 			{
197*03ce13f7SAndroid Build Coastguard Worker 				auto tx = Min(Max((x.Float(i) - edge0.Float(i)) / (edge1.Float(i) - edge0.Float(i)), 0.0f), 1.0f);
198*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, tx * tx * (3.0f - 2.0f * tx));
199*03ce13f7SAndroid Build Coastguard Worker 			}
200*03ce13f7SAndroid Build Coastguard Worker 		}
201*03ce13f7SAndroid Build Coastguard Worker 		break;
202*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FMix:
203*03ce13f7SAndroid Build Coastguard Worker 		{
204*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
205*03ce13f7SAndroid Build Coastguard Worker 			auto y = Operand(shader, *this, insn.word(6));
206*03ce13f7SAndroid Build Coastguard Worker 			auto a = Operand(shader, *this, insn.word(7));
207*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
208*03ce13f7SAndroid Build Coastguard Worker 			{
209*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, a.Float(i) * (y.Float(i) - x.Float(i)) + x.Float(i));
210*03ce13f7SAndroid Build Coastguard Worker 			}
211*03ce13f7SAndroid Build Coastguard Worker 		}
212*03ce13f7SAndroid Build Coastguard Worker 		break;
213*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FClamp:
214*03ce13f7SAndroid Build Coastguard Worker 		{
215*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
216*03ce13f7SAndroid Build Coastguard Worker 			auto minVal = Operand(shader, *this, insn.word(6));
217*03ce13f7SAndroid Build Coastguard Worker 			auto maxVal = Operand(shader, *this, insn.word(7));
218*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
219*03ce13f7SAndroid Build Coastguard Worker 			{
220*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Min(Max(x.Float(i), minVal.Float(i)), maxVal.Float(i)));
221*03ce13f7SAndroid Build Coastguard Worker 			}
222*03ce13f7SAndroid Build Coastguard Worker 		}
223*03ce13f7SAndroid Build Coastguard Worker 		break;
224*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450SClamp:
225*03ce13f7SAndroid Build Coastguard Worker 		{
226*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
227*03ce13f7SAndroid Build Coastguard Worker 			auto minVal = Operand(shader, *this, insn.word(6));
228*03ce13f7SAndroid Build Coastguard Worker 			auto maxVal = Operand(shader, *this, insn.word(7));
229*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
230*03ce13f7SAndroid Build Coastguard Worker 			{
231*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Min(Max(x.Int(i), minVal.Int(i)), maxVal.Int(i)));
232*03ce13f7SAndroid Build Coastguard Worker 			}
233*03ce13f7SAndroid Build Coastguard Worker 		}
234*03ce13f7SAndroid Build Coastguard Worker 		break;
235*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UClamp:
236*03ce13f7SAndroid Build Coastguard Worker 		{
237*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
238*03ce13f7SAndroid Build Coastguard Worker 			auto minVal = Operand(shader, *this, insn.word(6));
239*03ce13f7SAndroid Build Coastguard Worker 			auto maxVal = Operand(shader, *this, insn.word(7));
240*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
241*03ce13f7SAndroid Build Coastguard Worker 			{
242*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Min(Max(x.UInt(i), minVal.UInt(i)), maxVal.UInt(i)));
243*03ce13f7SAndroid Build Coastguard Worker 			}
244*03ce13f7SAndroid Build Coastguard Worker 		}
245*03ce13f7SAndroid Build Coastguard Worker 		break;
246*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FSign:
247*03ce13f7SAndroid Build Coastguard Worker 		{
248*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
249*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
250*03ce13f7SAndroid Build Coastguard Worker 			{
251*03ce13f7SAndroid Build Coastguard Worker 				auto neg = As<SIMD::Int>(CmpLT(src.Float(i), SIMD::Float(-0.0f))) & As<SIMD::Int>(SIMD::Float(-1.0f));
252*03ce13f7SAndroid Build Coastguard Worker 				auto pos = As<SIMD::Int>(CmpNLE(src.Float(i), SIMD::Float(+0.0f))) & As<SIMD::Int>(SIMD::Float(1.0f));
253*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, neg | pos);
254*03ce13f7SAndroid Build Coastguard Worker 			}
255*03ce13f7SAndroid Build Coastguard Worker 		}
256*03ce13f7SAndroid Build Coastguard Worker 		break;
257*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450SSign:
258*03ce13f7SAndroid Build Coastguard Worker 		{
259*03ce13f7SAndroid Build Coastguard Worker 			auto src = Operand(shader, *this, insn.word(5));
260*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
261*03ce13f7SAndroid Build Coastguard Worker 			{
262*03ce13f7SAndroid Build Coastguard Worker 				auto neg = CmpLT(src.Int(i), SIMD::Int(0)) & SIMD::Int(-1);
263*03ce13f7SAndroid Build Coastguard Worker 				auto pos = CmpNLE(src.Int(i), SIMD::Int(0)) & SIMD::Int(1);
264*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, neg | pos);
265*03ce13f7SAndroid Build Coastguard Worker 			}
266*03ce13f7SAndroid Build Coastguard Worker 		}
267*03ce13f7SAndroid Build Coastguard Worker 		break;
268*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Reflect:
269*03ce13f7SAndroid Build Coastguard Worker 		{
270*03ce13f7SAndroid Build Coastguard Worker 			auto I = Operand(shader, *this, insn.word(5));
271*03ce13f7SAndroid Build Coastguard Worker 			auto N = Operand(shader, *this, insn.word(6));
272*03ce13f7SAndroid Build Coastguard Worker 
273*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float d = FDot(type.componentCount, I, N);
274*03ce13f7SAndroid Build Coastguard Worker 
275*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
276*03ce13f7SAndroid Build Coastguard Worker 			{
277*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, I.Float(i) - SIMD::Float(2.0f) * d * N.Float(i));
278*03ce13f7SAndroid Build Coastguard Worker 			}
279*03ce13f7SAndroid Build Coastguard Worker 		}
280*03ce13f7SAndroid Build Coastguard Worker 		break;
281*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Refract:
282*03ce13f7SAndroid Build Coastguard Worker 		{
283*03ce13f7SAndroid Build Coastguard Worker 			auto I = Operand(shader, *this, insn.word(5));
284*03ce13f7SAndroid Build Coastguard Worker 			auto N = Operand(shader, *this, insn.word(6));
285*03ce13f7SAndroid Build Coastguard Worker 			auto eta = Operand(shader, *this, insn.word(7));
286*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations r = shader.GetDecorationsForId(insn.resultId());
287*03ce13f7SAndroid Build Coastguard Worker 
288*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float d = FDot(type.componentCount, I, N);
289*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float k = SIMD::Float(1.0f) - eta.Float(0) * eta.Float(0) * (SIMD::Float(1.0f) - d * d);
290*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Int pos = CmpNLT(k, SIMD::Float(0.0f));
291*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float t = (eta.Float(0) * d + Sqrt(k, r.RelaxedPrecision));
292*03ce13f7SAndroid Build Coastguard Worker 
293*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
294*03ce13f7SAndroid Build Coastguard Worker 			{
295*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, pos & As<SIMD::Int>(eta.Float(0) * I.Float(i) - t * N.Float(i)));
296*03ce13f7SAndroid Build Coastguard Worker 			}
297*03ce13f7SAndroid Build Coastguard Worker 		}
298*03ce13f7SAndroid Build Coastguard Worker 		break;
299*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FaceForward:
300*03ce13f7SAndroid Build Coastguard Worker 		{
301*03ce13f7SAndroid Build Coastguard Worker 			auto N = Operand(shader, *this, insn.word(5));
302*03ce13f7SAndroid Build Coastguard Worker 			auto I = Operand(shader, *this, insn.word(6));
303*03ce13f7SAndroid Build Coastguard Worker 			auto Nref = Operand(shader, *this, insn.word(7));
304*03ce13f7SAndroid Build Coastguard Worker 
305*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float d = FDot(type.componentCount, I, Nref);
306*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Int neg = CmpLT(d, SIMD::Float(0.0f));
307*03ce13f7SAndroid Build Coastguard Worker 
308*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
309*03ce13f7SAndroid Build Coastguard Worker 			{
310*03ce13f7SAndroid Build Coastguard Worker 				auto n = N.Float(i);
311*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, (neg & As<SIMD::Int>(n)) | (~neg & As<SIMD::Int>(-n)));
312*03ce13f7SAndroid Build Coastguard Worker 			}
313*03ce13f7SAndroid Build Coastguard Worker 		}
314*03ce13f7SAndroid Build Coastguard Worker 		break;
315*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Length:
316*03ce13f7SAndroid Build Coastguard Worker 		{
317*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
318*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float d = FDot(shader.getObjectType(insn.word(5)).componentCount, x, x);
319*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations r = shader.GetDecorationsForId(insn.resultId());
320*03ce13f7SAndroid Build Coastguard Worker 
321*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, Sqrt(d, r.RelaxedPrecision));
322*03ce13f7SAndroid Build Coastguard Worker 		}
323*03ce13f7SAndroid Build Coastguard Worker 		break;
324*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Normalize:
325*03ce13f7SAndroid Build Coastguard Worker 		{
326*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
327*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations r = shader.GetDecorationsForId(insn.resultId());
328*03ce13f7SAndroid Build Coastguard Worker 
329*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float d = FDot(shader.getObjectType(insn.word(5)).componentCount, x, x);
330*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float invLength = SIMD::Float(1.0f) / Sqrt(d, r.RelaxedPrecision);
331*03ce13f7SAndroid Build Coastguard Worker 
332*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
333*03ce13f7SAndroid Build Coastguard Worker 			{
334*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, invLength * x.Float(i));
335*03ce13f7SAndroid Build Coastguard Worker 			}
336*03ce13f7SAndroid Build Coastguard Worker 		}
337*03ce13f7SAndroid Build Coastguard Worker 		break;
338*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Distance:
339*03ce13f7SAndroid Build Coastguard Worker 		{
340*03ce13f7SAndroid Build Coastguard Worker 			auto p0 = Operand(shader, *this, insn.word(5));
341*03ce13f7SAndroid Build Coastguard Worker 			auto p1 = Operand(shader, *this, insn.word(6));
342*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations r = shader.GetDecorationsForId(insn.resultId());
343*03ce13f7SAndroid Build Coastguard Worker 
344*03ce13f7SAndroid Build Coastguard Worker 			// sqrt(dot(p0-p1, p0-p1))
345*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Float d = (p0.Float(0) - p1.Float(0)) * (p0.Float(0) - p1.Float(0));
346*03ce13f7SAndroid Build Coastguard Worker 
347*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 1u; i < p0.componentCount; i++)
348*03ce13f7SAndroid Build Coastguard Worker 			{
349*03ce13f7SAndroid Build Coastguard Worker 				d += (p0.Float(i) - p1.Float(i)) * (p0.Float(i) - p1.Float(i));
350*03ce13f7SAndroid Build Coastguard Worker 			}
351*03ce13f7SAndroid Build Coastguard Worker 
352*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, Sqrt(d, r.RelaxedPrecision));
353*03ce13f7SAndroid Build Coastguard Worker 		}
354*03ce13f7SAndroid Build Coastguard Worker 		break;
355*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Modf:
356*03ce13f7SAndroid Build Coastguard Worker 		{
357*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
358*03ce13f7SAndroid Build Coastguard Worker 			auto ptrId = Spirv::Object::ID(insn.word(6));
359*03ce13f7SAndroid Build Coastguard Worker 
360*03ce13f7SAndroid Build Coastguard Worker 			Intermediate whole(type.componentCount);
361*03ce13f7SAndroid Build Coastguard Worker 
362*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
363*03ce13f7SAndroid Build Coastguard Worker 			{
364*03ce13f7SAndroid Build Coastguard Worker 				auto wholeAndFrac = Modf(val.Float(i));
365*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, wholeAndFrac.second);
366*03ce13f7SAndroid Build Coastguard Worker 				whole.move(i, wholeAndFrac.first);
367*03ce13f7SAndroid Build Coastguard Worker 			}
368*03ce13f7SAndroid Build Coastguard Worker 
369*03ce13f7SAndroid Build Coastguard Worker 			Store(ptrId, whole, false, std::memory_order_relaxed);
370*03ce13f7SAndroid Build Coastguard Worker 		}
371*03ce13f7SAndroid Build Coastguard Worker 		break;
372*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450ModfStruct:
373*03ce13f7SAndroid Build Coastguard Worker 		{
374*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
375*03ce13f7SAndroid Build Coastguard Worker 
376*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < val.componentCount; i++)
377*03ce13f7SAndroid Build Coastguard Worker 			{
378*03ce13f7SAndroid Build Coastguard Worker 				auto wholeAndFrac = Modf(val.Float(i));
379*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, wholeAndFrac.second);
380*03ce13f7SAndroid Build Coastguard Worker 				dst.move(val.componentCount + i, wholeAndFrac.first);
381*03ce13f7SAndroid Build Coastguard Worker 			}
382*03ce13f7SAndroid Build Coastguard Worker 		}
383*03ce13f7SAndroid Build Coastguard Worker 		break;
384*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450PackSnorm4x8:
385*03ce13f7SAndroid Build Coastguard Worker 		{
386*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
387*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, (SIMD::Int(Round(Min(Max(val.Float(0), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(127.0f))) &
388*03ce13f7SAndroid Build Coastguard Worker 			             SIMD::Int(0xFF)) |
389*03ce13f7SAndroid Build Coastguard Worker 			                ((SIMD::Int(Round(Min(Max(val.Float(1), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(127.0f))) &
390*03ce13f7SAndroid Build Coastguard Worker 			                  SIMD::Int(0xFF))
391*03ce13f7SAndroid Build Coastguard Worker 			                 << 8) |
392*03ce13f7SAndroid Build Coastguard Worker 			                ((SIMD::Int(Round(Min(Max(val.Float(2), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(127.0f))) &
393*03ce13f7SAndroid Build Coastguard Worker 			                  SIMD::Int(0xFF))
394*03ce13f7SAndroid Build Coastguard Worker 			                 << 16) |
395*03ce13f7SAndroid Build Coastguard Worker 			                ((SIMD::Int(Round(Min(Max(val.Float(3), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(127.0f))) &
396*03ce13f7SAndroid Build Coastguard Worker 			                  SIMD::Int(0xFF))
397*03ce13f7SAndroid Build Coastguard Worker 			                 << 24));
398*03ce13f7SAndroid Build Coastguard Worker 		}
399*03ce13f7SAndroid Build Coastguard Worker 		break;
400*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450PackUnorm4x8:
401*03ce13f7SAndroid Build Coastguard Worker 		{
402*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
403*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, (SIMD::UInt(Round(Min(Max(val.Float(0), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(255.0f)))) |
404*03ce13f7SAndroid Build Coastguard Worker 			                ((SIMD::UInt(Round(Min(Max(val.Float(1), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(255.0f)))) << 8) |
405*03ce13f7SAndroid Build Coastguard Worker 			                ((SIMD::UInt(Round(Min(Max(val.Float(2), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(255.0f)))) << 16) |
406*03ce13f7SAndroid Build Coastguard Worker 			                ((SIMD::UInt(Round(Min(Max(val.Float(3), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(255.0f)))) << 24));
407*03ce13f7SAndroid Build Coastguard Worker 		}
408*03ce13f7SAndroid Build Coastguard Worker 		break;
409*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450PackSnorm2x16:
410*03ce13f7SAndroid Build Coastguard Worker 		{
411*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
412*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, (SIMD::Int(Round(Min(Max(val.Float(0), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(32767.0f))) &
413*03ce13f7SAndroid Build Coastguard Worker 			             SIMD::Int(0xFFFF)) |
414*03ce13f7SAndroid Build Coastguard Worker 			                ((SIMD::Int(Round(Min(Max(val.Float(1), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(32767.0f))) &
415*03ce13f7SAndroid Build Coastguard Worker 			                  SIMD::Int(0xFFFF))
416*03ce13f7SAndroid Build Coastguard Worker 			                 << 16));
417*03ce13f7SAndroid Build Coastguard Worker 		}
418*03ce13f7SAndroid Build Coastguard Worker 		break;
419*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450PackUnorm2x16:
420*03ce13f7SAndroid Build Coastguard Worker 		{
421*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
422*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, (SIMD::UInt(Round(Min(Max(val.Float(0), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(65535.0f))) &
423*03ce13f7SAndroid Build Coastguard Worker 			             SIMD::UInt(0xFFFF)) |
424*03ce13f7SAndroid Build Coastguard Worker 			                ((SIMD::UInt(Round(Min(Max(val.Float(1), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(65535.0f))) &
425*03ce13f7SAndroid Build Coastguard Worker 			                  SIMD::UInt(0xFFFF))
426*03ce13f7SAndroid Build Coastguard Worker 			                 << 16));
427*03ce13f7SAndroid Build Coastguard Worker 		}
428*03ce13f7SAndroid Build Coastguard Worker 		break;
429*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450PackHalf2x16:
430*03ce13f7SAndroid Build Coastguard Worker 		{
431*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
432*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, floatToHalfBits(val.UInt(0), false) | floatToHalfBits(val.UInt(1), true));
433*03ce13f7SAndroid Build Coastguard Worker 		}
434*03ce13f7SAndroid Build Coastguard Worker 		break;
435*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UnpackSnorm4x8:
436*03ce13f7SAndroid Build Coastguard Worker 		{
437*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
438*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, Min(Max(SIMD::Float(((val.Int(0) << 24) & SIMD::Int(0xFF000000))) * SIMD::Float(1.0f / float(0x7f000000)), SIMD::Float(-1.0f)), SIMD::Float(1.0f)));
439*03ce13f7SAndroid Build Coastguard Worker 			dst.move(1, Min(Max(SIMD::Float(((val.Int(0) << 16) & SIMD::Int(0xFF000000))) * SIMD::Float(1.0f / float(0x7f000000)), SIMD::Float(-1.0f)), SIMD::Float(1.0f)));
440*03ce13f7SAndroid Build Coastguard Worker 			dst.move(2, Min(Max(SIMD::Float(((val.Int(0) << 8) & SIMD::Int(0xFF000000))) * SIMD::Float(1.0f / float(0x7f000000)), SIMD::Float(-1.0f)), SIMD::Float(1.0f)));
441*03ce13f7SAndroid Build Coastguard Worker 			dst.move(3, Min(Max(SIMD::Float(((val.Int(0)) & SIMD::Int(0xFF000000))) * SIMD::Float(1.0f / float(0x7f000000)), SIMD::Float(-1.0f)), SIMD::Float(1.0f)));
442*03ce13f7SAndroid Build Coastguard Worker 		}
443*03ce13f7SAndroid Build Coastguard Worker 		break;
444*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UnpackUnorm4x8:
445*03ce13f7SAndroid Build Coastguard Worker 		{
446*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
447*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, SIMD::Float((val.UInt(0) & SIMD::UInt(0xFF))) * SIMD::Float(1.0f / 255.f));
448*03ce13f7SAndroid Build Coastguard Worker 			dst.move(1, SIMD::Float(((val.UInt(0) >> 8) & SIMD::UInt(0xFF))) * SIMD::Float(1.0f / 255.f));
449*03ce13f7SAndroid Build Coastguard Worker 			dst.move(2, SIMD::Float(((val.UInt(0) >> 16) & SIMD::UInt(0xFF))) * SIMD::Float(1.0f / 255.f));
450*03ce13f7SAndroid Build Coastguard Worker 			dst.move(3, SIMD::Float(((val.UInt(0) >> 24) & SIMD::UInt(0xFF))) * SIMD::Float(1.0f / 255.f));
451*03ce13f7SAndroid Build Coastguard Worker 		}
452*03ce13f7SAndroid Build Coastguard Worker 		break;
453*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UnpackSnorm2x16:
454*03ce13f7SAndroid Build Coastguard Worker 		{
455*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
456*03ce13f7SAndroid Build Coastguard Worker 			// clamp(f / 32767.0, -1.0, 1.0)
457*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, Min(Max(SIMD::Float(As<SIMD::Int>((val.UInt(0) & SIMD::UInt(0x0000FFFF)) << 16)) *
458*03ce13f7SAndroid Build Coastguard Worker 			                        SIMD::Float(1.0f / float(0x7FFF0000)),
459*03ce13f7SAndroid Build Coastguard Worker 			                    SIMD::Float(-1.0f)),
460*03ce13f7SAndroid Build Coastguard Worker 			                SIMD::Float(1.0f)));
461*03ce13f7SAndroid Build Coastguard Worker 			dst.move(1, Min(Max(SIMD::Float(As<SIMD::Int>(val.UInt(0) & SIMD::UInt(0xFFFF0000))) * SIMD::Float(1.0f / float(0x7FFF0000)),
462*03ce13f7SAndroid Build Coastguard Worker 			                    SIMD::Float(-1.0f)),
463*03ce13f7SAndroid Build Coastguard Worker 			                SIMD::Float(1.0f)));
464*03ce13f7SAndroid Build Coastguard Worker 		}
465*03ce13f7SAndroid Build Coastguard Worker 		break;
466*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UnpackUnorm2x16:
467*03ce13f7SAndroid Build Coastguard Worker 		{
468*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
469*03ce13f7SAndroid Build Coastguard Worker 			// f / 65535.0
470*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, SIMD::Float((val.UInt(0) & SIMD::UInt(0x0000FFFF)) << 16) * SIMD::Float(1.0f / float(0xFFFF0000)));
471*03ce13f7SAndroid Build Coastguard Worker 			dst.move(1, SIMD::Float(val.UInt(0) & SIMD::UInt(0xFFFF0000)) * SIMD::Float(1.0f / float(0xFFFF0000)));
472*03ce13f7SAndroid Build Coastguard Worker 		}
473*03ce13f7SAndroid Build Coastguard Worker 		break;
474*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UnpackHalf2x16:
475*03ce13f7SAndroid Build Coastguard Worker 		{
476*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
477*03ce13f7SAndroid Build Coastguard Worker 			dst.move(0, halfToFloatBits(val.UInt(0) & SIMD::UInt(0x0000FFFF)));
478*03ce13f7SAndroid Build Coastguard Worker 			dst.move(1, halfToFloatBits((val.UInt(0) & SIMD::UInt(0xFFFF0000)) >> 16));
479*03ce13f7SAndroid Build Coastguard Worker 		}
480*03ce13f7SAndroid Build Coastguard Worker 		break;
481*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Fma:
482*03ce13f7SAndroid Build Coastguard Worker 		{
483*03ce13f7SAndroid Build Coastguard Worker 			auto a = Operand(shader, *this, insn.word(5));
484*03ce13f7SAndroid Build Coastguard Worker 			auto b = Operand(shader, *this, insn.word(6));
485*03ce13f7SAndroid Build Coastguard Worker 			auto c = Operand(shader, *this, insn.word(7));
486*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
487*03ce13f7SAndroid Build Coastguard Worker 			{
488*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, MulAdd(a.Float(i), b.Float(i), c.Float(i)));
489*03ce13f7SAndroid Build Coastguard Worker 			}
490*03ce13f7SAndroid Build Coastguard Worker 		}
491*03ce13f7SAndroid Build Coastguard Worker 		break;
492*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Frexp:
493*03ce13f7SAndroid Build Coastguard Worker 		{
494*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
495*03ce13f7SAndroid Build Coastguard Worker 			auto ptrId = Spirv::Object::ID(insn.word(6));
496*03ce13f7SAndroid Build Coastguard Worker 
497*03ce13f7SAndroid Build Coastguard Worker 			Intermediate exp(type.componentCount);
498*03ce13f7SAndroid Build Coastguard Worker 
499*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
500*03ce13f7SAndroid Build Coastguard Worker 			{
501*03ce13f7SAndroid Build Coastguard Worker 				auto significandAndExponent = Frexp(val.Float(i));
502*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, significandAndExponent.first);
503*03ce13f7SAndroid Build Coastguard Worker 				exp.move(i, significandAndExponent.second);
504*03ce13f7SAndroid Build Coastguard Worker 			}
505*03ce13f7SAndroid Build Coastguard Worker 
506*03ce13f7SAndroid Build Coastguard Worker 			Store(ptrId, exp, false, std::memory_order_relaxed);
507*03ce13f7SAndroid Build Coastguard Worker 		}
508*03ce13f7SAndroid Build Coastguard Worker 		break;
509*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FrexpStruct:
510*03ce13f7SAndroid Build Coastguard Worker 		{
511*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
512*03ce13f7SAndroid Build Coastguard Worker 
513*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < val.componentCount; i++)
514*03ce13f7SAndroid Build Coastguard Worker 			{
515*03ce13f7SAndroid Build Coastguard Worker 				auto significandAndExponent = Frexp(val.Float(i));
516*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, significandAndExponent.first);
517*03ce13f7SAndroid Build Coastguard Worker 				dst.move(val.componentCount + i, significandAndExponent.second);
518*03ce13f7SAndroid Build Coastguard Worker 			}
519*03ce13f7SAndroid Build Coastguard Worker 		}
520*03ce13f7SAndroid Build Coastguard Worker 		break;
521*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Ldexp:
522*03ce13f7SAndroid Build Coastguard Worker 		{
523*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
524*03ce13f7SAndroid Build Coastguard Worker 			auto exp = Operand(shader, *this, insn.word(6));
525*03ce13f7SAndroid Build Coastguard Worker 
526*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
527*03ce13f7SAndroid Build Coastguard Worker 			{
528*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Ldexp(x.Float(i), exp.Int(i)));
529*03ce13f7SAndroid Build Coastguard Worker 			}
530*03ce13f7SAndroid Build Coastguard Worker 		}
531*03ce13f7SAndroid Build Coastguard Worker 		break;
532*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Radians:
533*03ce13f7SAndroid Build Coastguard Worker 		{
534*03ce13f7SAndroid Build Coastguard Worker 			auto degrees = Operand(shader, *this, insn.word(5));
535*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
536*03ce13f7SAndroid Build Coastguard Worker 			{
537*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, degrees.Float(i) * SIMD::Float(PI / 180.0f));
538*03ce13f7SAndroid Build Coastguard Worker 			}
539*03ce13f7SAndroid Build Coastguard Worker 		}
540*03ce13f7SAndroid Build Coastguard Worker 		break;
541*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Degrees:
542*03ce13f7SAndroid Build Coastguard Worker 		{
543*03ce13f7SAndroid Build Coastguard Worker 			auto radians = Operand(shader, *this, insn.word(5));
544*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
545*03ce13f7SAndroid Build Coastguard Worker 			{
546*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, radians.Float(i) * SIMD::Float(180.0f / PI));
547*03ce13f7SAndroid Build Coastguard Worker 			}
548*03ce13f7SAndroid Build Coastguard Worker 		}
549*03ce13f7SAndroid Build Coastguard Worker 		break;
550*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Sin:
551*03ce13f7SAndroid Build Coastguard Worker 		{
552*03ce13f7SAndroid Build Coastguard Worker 			auto radians = Operand(shader, *this, insn.word(5));
553*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
554*03ce13f7SAndroid Build Coastguard Worker 
555*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
556*03ce13f7SAndroid Build Coastguard Worker 			{
557*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Sin(radians.Float(i), d.RelaxedPrecision));
558*03ce13f7SAndroid Build Coastguard Worker 			}
559*03ce13f7SAndroid Build Coastguard Worker 		}
560*03ce13f7SAndroid Build Coastguard Worker 		break;
561*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Cos:
562*03ce13f7SAndroid Build Coastguard Worker 		{
563*03ce13f7SAndroid Build Coastguard Worker 			auto radians = Operand(shader, *this, insn.word(5));
564*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
565*03ce13f7SAndroid Build Coastguard Worker 
566*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
567*03ce13f7SAndroid Build Coastguard Worker 			{
568*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Cos(radians.Float(i), d.RelaxedPrecision));
569*03ce13f7SAndroid Build Coastguard Worker 			}
570*03ce13f7SAndroid Build Coastguard Worker 		}
571*03ce13f7SAndroid Build Coastguard Worker 		break;
572*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Tan:
573*03ce13f7SAndroid Build Coastguard Worker 		{
574*03ce13f7SAndroid Build Coastguard Worker 			auto radians = Operand(shader, *this, insn.word(5));
575*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
576*03ce13f7SAndroid Build Coastguard Worker 
577*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
578*03ce13f7SAndroid Build Coastguard Worker 			{
579*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Tan(radians.Float(i), d.RelaxedPrecision));
580*03ce13f7SAndroid Build Coastguard Worker 			}
581*03ce13f7SAndroid Build Coastguard Worker 		}
582*03ce13f7SAndroid Build Coastguard Worker 		break;
583*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Asin:
584*03ce13f7SAndroid Build Coastguard Worker 		{
585*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
586*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
587*03ce13f7SAndroid Build Coastguard Worker 
588*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
589*03ce13f7SAndroid Build Coastguard Worker 			{
590*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Asin(val.Float(i), d.RelaxedPrecision));
591*03ce13f7SAndroid Build Coastguard Worker 			}
592*03ce13f7SAndroid Build Coastguard Worker 		}
593*03ce13f7SAndroid Build Coastguard Worker 		break;
594*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Acos:
595*03ce13f7SAndroid Build Coastguard Worker 		{
596*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
597*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
598*03ce13f7SAndroid Build Coastguard Worker 
599*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
600*03ce13f7SAndroid Build Coastguard Worker 			{
601*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Acos(val.Float(i), d.RelaxedPrecision));
602*03ce13f7SAndroid Build Coastguard Worker 			}
603*03ce13f7SAndroid Build Coastguard Worker 		}
604*03ce13f7SAndroid Build Coastguard Worker 		break;
605*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Atan:
606*03ce13f7SAndroid Build Coastguard Worker 		{
607*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
608*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
609*03ce13f7SAndroid Build Coastguard Worker 
610*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
611*03ce13f7SAndroid Build Coastguard Worker 			{
612*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Atan(val.Float(i), d.RelaxedPrecision));
613*03ce13f7SAndroid Build Coastguard Worker 			}
614*03ce13f7SAndroid Build Coastguard Worker 		}
615*03ce13f7SAndroid Build Coastguard Worker 		break;
616*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Sinh:
617*03ce13f7SAndroid Build Coastguard Worker 		{
618*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
619*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
620*03ce13f7SAndroid Build Coastguard Worker 
621*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
622*03ce13f7SAndroid Build Coastguard Worker 			{
623*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Sinh(val.Float(i), d.RelaxedPrecision));
624*03ce13f7SAndroid Build Coastguard Worker 			}
625*03ce13f7SAndroid Build Coastguard Worker 		}
626*03ce13f7SAndroid Build Coastguard Worker 		break;
627*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Cosh:
628*03ce13f7SAndroid Build Coastguard Worker 		{
629*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
630*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
631*03ce13f7SAndroid Build Coastguard Worker 
632*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
633*03ce13f7SAndroid Build Coastguard Worker 			{
634*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Cosh(val.Float(i), d.RelaxedPrecision));
635*03ce13f7SAndroid Build Coastguard Worker 			}
636*03ce13f7SAndroid Build Coastguard Worker 		}
637*03ce13f7SAndroid Build Coastguard Worker 		break;
638*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Tanh:
639*03ce13f7SAndroid Build Coastguard Worker 		{
640*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
641*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
642*03ce13f7SAndroid Build Coastguard Worker 
643*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
644*03ce13f7SAndroid Build Coastguard Worker 			{
645*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Tanh(val.Float(i), d.RelaxedPrecision));
646*03ce13f7SAndroid Build Coastguard Worker 			}
647*03ce13f7SAndroid Build Coastguard Worker 		}
648*03ce13f7SAndroid Build Coastguard Worker 		break;
649*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Asinh:
650*03ce13f7SAndroid Build Coastguard Worker 		{
651*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
652*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
653*03ce13f7SAndroid Build Coastguard Worker 
654*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
655*03ce13f7SAndroid Build Coastguard Worker 			{
656*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Asinh(val.Float(i), d.RelaxedPrecision));
657*03ce13f7SAndroid Build Coastguard Worker 			}
658*03ce13f7SAndroid Build Coastguard Worker 		}
659*03ce13f7SAndroid Build Coastguard Worker 		break;
660*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Acosh:
661*03ce13f7SAndroid Build Coastguard Worker 		{
662*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
663*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
664*03ce13f7SAndroid Build Coastguard Worker 
665*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
666*03ce13f7SAndroid Build Coastguard Worker 			{
667*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Acosh(val.Float(i), d.RelaxedPrecision));
668*03ce13f7SAndroid Build Coastguard Worker 			}
669*03ce13f7SAndroid Build Coastguard Worker 		}
670*03ce13f7SAndroid Build Coastguard Worker 		break;
671*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Atanh:
672*03ce13f7SAndroid Build Coastguard Worker 		{
673*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
674*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
675*03ce13f7SAndroid Build Coastguard Worker 
676*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
677*03ce13f7SAndroid Build Coastguard Worker 			{
678*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Atanh(val.Float(i), d.RelaxedPrecision));
679*03ce13f7SAndroid Build Coastguard Worker 			}
680*03ce13f7SAndroid Build Coastguard Worker 		}
681*03ce13f7SAndroid Build Coastguard Worker 		break;
682*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Atan2:
683*03ce13f7SAndroid Build Coastguard Worker 		{
684*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
685*03ce13f7SAndroid Build Coastguard Worker 			auto y = Operand(shader, *this, insn.word(6));
686*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
687*03ce13f7SAndroid Build Coastguard Worker 
688*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
689*03ce13f7SAndroid Build Coastguard Worker 			{
690*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Atan2(x.Float(i), y.Float(i), d.RelaxedPrecision));
691*03ce13f7SAndroid Build Coastguard Worker 			}
692*03ce13f7SAndroid Build Coastguard Worker 		}
693*03ce13f7SAndroid Build Coastguard Worker 		break;
694*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Pow:
695*03ce13f7SAndroid Build Coastguard Worker 		{
696*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
697*03ce13f7SAndroid Build Coastguard Worker 			auto y = Operand(shader, *this, insn.word(6));
698*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
699*03ce13f7SAndroid Build Coastguard Worker 
700*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
701*03ce13f7SAndroid Build Coastguard Worker 			{
702*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Pow(x.Float(i), y.Float(i), d.RelaxedPrecision));
703*03ce13f7SAndroid Build Coastguard Worker 			}
704*03ce13f7SAndroid Build Coastguard Worker 		}
705*03ce13f7SAndroid Build Coastguard Worker 		break;
706*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Exp:
707*03ce13f7SAndroid Build Coastguard Worker 		{
708*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
709*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
710*03ce13f7SAndroid Build Coastguard Worker 
711*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
712*03ce13f7SAndroid Build Coastguard Worker 			{
713*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Exp(val.Float(i), d.RelaxedPrecision));
714*03ce13f7SAndroid Build Coastguard Worker 			}
715*03ce13f7SAndroid Build Coastguard Worker 		}
716*03ce13f7SAndroid Build Coastguard Worker 		break;
717*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Log:
718*03ce13f7SAndroid Build Coastguard Worker 		{
719*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
720*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
721*03ce13f7SAndroid Build Coastguard Worker 
722*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
723*03ce13f7SAndroid Build Coastguard Worker 			{
724*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Log(val.Float(i), d.RelaxedPrecision));
725*03ce13f7SAndroid Build Coastguard Worker 			}
726*03ce13f7SAndroid Build Coastguard Worker 		}
727*03ce13f7SAndroid Build Coastguard Worker 		break;
728*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Exp2:
729*03ce13f7SAndroid Build Coastguard Worker 		{
730*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
731*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
732*03ce13f7SAndroid Build Coastguard Worker 
733*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
734*03ce13f7SAndroid Build Coastguard Worker 			{
735*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Exp2(val.Float(i), d.RelaxedPrecision));
736*03ce13f7SAndroid Build Coastguard Worker 			}
737*03ce13f7SAndroid Build Coastguard Worker 		}
738*03ce13f7SAndroid Build Coastguard Worker 		break;
739*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Log2:
740*03ce13f7SAndroid Build Coastguard Worker 		{
741*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
742*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
743*03ce13f7SAndroid Build Coastguard Worker 
744*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
745*03ce13f7SAndroid Build Coastguard Worker 			{
746*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Log2(val.Float(i), d.RelaxedPrecision));
747*03ce13f7SAndroid Build Coastguard Worker 			}
748*03ce13f7SAndroid Build Coastguard Worker 		}
749*03ce13f7SAndroid Build Coastguard Worker 		break;
750*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Sqrt:
751*03ce13f7SAndroid Build Coastguard Worker 		{
752*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
753*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
754*03ce13f7SAndroid Build Coastguard Worker 
755*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
756*03ce13f7SAndroid Build Coastguard Worker 			{
757*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Sqrt(val.Float(i), d.RelaxedPrecision));
758*03ce13f7SAndroid Build Coastguard Worker 			}
759*03ce13f7SAndroid Build Coastguard Worker 		}
760*03ce13f7SAndroid Build Coastguard Worker 		break;
761*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450InverseSqrt:
762*03ce13f7SAndroid Build Coastguard Worker 		{
763*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
764*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.resultId());
765*03ce13f7SAndroid Build Coastguard Worker 
766*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
767*03ce13f7SAndroid Build Coastguard Worker 			{
768*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, RcpSqrt(val.Float(i), d.RelaxedPrecision));
769*03ce13f7SAndroid Build Coastguard Worker 			}
770*03ce13f7SAndroid Build Coastguard Worker 		}
771*03ce13f7SAndroid Build Coastguard Worker 		break;
772*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450Determinant:
773*03ce13f7SAndroid Build Coastguard Worker 		{
774*03ce13f7SAndroid Build Coastguard Worker 			auto mat = Operand(shader, *this, insn.word(5));
775*03ce13f7SAndroid Build Coastguard Worker 
776*03ce13f7SAndroid Build Coastguard Worker 			switch(mat.componentCount)
777*03ce13f7SAndroid Build Coastguard Worker 			{
778*03ce13f7SAndroid Build Coastguard Worker 			case 4:  // 2x2
779*03ce13f7SAndroid Build Coastguard Worker 				dst.move(0, Determinant(
780*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(0), mat.Float(1),
781*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(2), mat.Float(3)));
782*03ce13f7SAndroid Build Coastguard Worker 				break;
783*03ce13f7SAndroid Build Coastguard Worker 			case 9:  // 3x3
784*03ce13f7SAndroid Build Coastguard Worker 				dst.move(0, Determinant(
785*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(0), mat.Float(1), mat.Float(2),
786*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(3), mat.Float(4), mat.Float(5),
787*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(6), mat.Float(7), mat.Float(8)));
788*03ce13f7SAndroid Build Coastguard Worker 				break;
789*03ce13f7SAndroid Build Coastguard Worker 			case 16:  // 4x4
790*03ce13f7SAndroid Build Coastguard Worker 				dst.move(0, Determinant(
791*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(0), mat.Float(1), mat.Float(2), mat.Float(3),
792*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(4), mat.Float(5), mat.Float(6), mat.Float(7),
793*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(8), mat.Float(9), mat.Float(10), mat.Float(11),
794*03ce13f7SAndroid Build Coastguard Worker 				                mat.Float(12), mat.Float(13), mat.Float(14), mat.Float(15)));
795*03ce13f7SAndroid Build Coastguard Worker 				break;
796*03ce13f7SAndroid Build Coastguard Worker 			default:
797*03ce13f7SAndroid Build Coastguard Worker 				UNREACHABLE("GLSLstd450Determinant can only operate with square matrices. Got %d elements", int(mat.componentCount));
798*03ce13f7SAndroid Build Coastguard Worker 			}
799*03ce13f7SAndroid Build Coastguard Worker 		}
800*03ce13f7SAndroid Build Coastguard Worker 		break;
801*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450MatrixInverse:
802*03ce13f7SAndroid Build Coastguard Worker 		{
803*03ce13f7SAndroid Build Coastguard Worker 			auto mat = Operand(shader, *this, insn.word(5));
804*03ce13f7SAndroid Build Coastguard Worker 
805*03ce13f7SAndroid Build Coastguard Worker 			switch(mat.componentCount)
806*03ce13f7SAndroid Build Coastguard Worker 			{
807*03ce13f7SAndroid Build Coastguard Worker 			case 4:  // 2x2
808*03ce13f7SAndroid Build Coastguard Worker 				{
809*03ce13f7SAndroid Build Coastguard Worker 					auto inv = MatrixInverse(
810*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(0), mat.Float(1),
811*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(2), mat.Float(3));
812*03ce13f7SAndroid Build Coastguard Worker 					for(uint32_t i = 0; i < inv.size(); i++)
813*03ce13f7SAndroid Build Coastguard Worker 					{
814*03ce13f7SAndroid Build Coastguard Worker 						dst.move(i, inv[i]);
815*03ce13f7SAndroid Build Coastguard Worker 					}
816*03ce13f7SAndroid Build Coastguard Worker 				}
817*03ce13f7SAndroid Build Coastguard Worker 				break;
818*03ce13f7SAndroid Build Coastguard Worker 			case 9:  // 3x3
819*03ce13f7SAndroid Build Coastguard Worker 				{
820*03ce13f7SAndroid Build Coastguard Worker 					auto inv = MatrixInverse(
821*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(0), mat.Float(1), mat.Float(2),
822*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(3), mat.Float(4), mat.Float(5),
823*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(6), mat.Float(7), mat.Float(8));
824*03ce13f7SAndroid Build Coastguard Worker 					for(uint32_t i = 0; i < inv.size(); i++)
825*03ce13f7SAndroid Build Coastguard Worker 					{
826*03ce13f7SAndroid Build Coastguard Worker 						dst.move(i, inv[i]);
827*03ce13f7SAndroid Build Coastguard Worker 					}
828*03ce13f7SAndroid Build Coastguard Worker 				}
829*03ce13f7SAndroid Build Coastguard Worker 				break;
830*03ce13f7SAndroid Build Coastguard Worker 			case 16:  // 4x4
831*03ce13f7SAndroid Build Coastguard Worker 				{
832*03ce13f7SAndroid Build Coastguard Worker 					auto inv = MatrixInverse(
833*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(0), mat.Float(1), mat.Float(2), mat.Float(3),
834*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(4), mat.Float(5), mat.Float(6), mat.Float(7),
835*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(8), mat.Float(9), mat.Float(10), mat.Float(11),
836*03ce13f7SAndroid Build Coastguard Worker 					    mat.Float(12), mat.Float(13), mat.Float(14), mat.Float(15));
837*03ce13f7SAndroid Build Coastguard Worker 					for(uint32_t i = 0; i < inv.size(); i++)
838*03ce13f7SAndroid Build Coastguard Worker 					{
839*03ce13f7SAndroid Build Coastguard Worker 						dst.move(i, inv[i]);
840*03ce13f7SAndroid Build Coastguard Worker 					}
841*03ce13f7SAndroid Build Coastguard Worker 				}
842*03ce13f7SAndroid Build Coastguard Worker 				break;
843*03ce13f7SAndroid Build Coastguard Worker 			default:
844*03ce13f7SAndroid Build Coastguard Worker 				UNREACHABLE("GLSLstd450MatrixInverse can only operate with square matrices. Got %d elements", int(mat.componentCount));
845*03ce13f7SAndroid Build Coastguard Worker 			}
846*03ce13f7SAndroid Build Coastguard Worker 		}
847*03ce13f7SAndroid Build Coastguard Worker 		break;
848*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450IMix:
849*03ce13f7SAndroid Build Coastguard Worker 		{
850*03ce13f7SAndroid Build Coastguard Worker 			UNREACHABLE("GLSLstd450IMix has been removed from the specification");
851*03ce13f7SAndroid Build Coastguard Worker 		}
852*03ce13f7SAndroid Build Coastguard Worker 		break;
853*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450PackDouble2x32:
854*03ce13f7SAndroid Build Coastguard Worker 		{
855*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("SPIR-V Float64 Capability (GLSLstd450PackDouble2x32)");
856*03ce13f7SAndroid Build Coastguard Worker 		}
857*03ce13f7SAndroid Build Coastguard Worker 		break;
858*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450UnpackDouble2x32:
859*03ce13f7SAndroid Build Coastguard Worker 		{
860*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("SPIR-V Float64 Capability (GLSLstd450UnpackDouble2x32)");
861*03ce13f7SAndroid Build Coastguard Worker 		}
862*03ce13f7SAndroid Build Coastguard Worker 		break;
863*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FindILsb:
864*03ce13f7SAndroid Build Coastguard Worker 		{
865*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
866*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
867*03ce13f7SAndroid Build Coastguard Worker 			{
868*03ce13f7SAndroid Build Coastguard Worker 				auto v = val.UInt(i);
869*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, Cttz(v, false) | CmpEQ(v, SIMD::UInt(0)));
870*03ce13f7SAndroid Build Coastguard Worker 			}
871*03ce13f7SAndroid Build Coastguard Worker 		}
872*03ce13f7SAndroid Build Coastguard Worker 		break;
873*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FindSMsb:
874*03ce13f7SAndroid Build Coastguard Worker 		{
875*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
876*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
877*03ce13f7SAndroid Build Coastguard Worker 			{
878*03ce13f7SAndroid Build Coastguard Worker 				auto v = val.UInt(i) ^ As<SIMD::UInt>(CmpLT(val.Int(i), SIMD::Int(0)));
879*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, SIMD::UInt(31) - Ctlz(v, false));
880*03ce13f7SAndroid Build Coastguard Worker 			}
881*03ce13f7SAndroid Build Coastguard Worker 		}
882*03ce13f7SAndroid Build Coastguard Worker 		break;
883*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450FindUMsb:
884*03ce13f7SAndroid Build Coastguard Worker 		{
885*03ce13f7SAndroid Build Coastguard Worker 			auto val = Operand(shader, *this, insn.word(5));
886*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
887*03ce13f7SAndroid Build Coastguard Worker 			{
888*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, SIMD::UInt(31) - Ctlz(val.UInt(i), false));
889*03ce13f7SAndroid Build Coastguard Worker 			}
890*03ce13f7SAndroid Build Coastguard Worker 		}
891*03ce13f7SAndroid Build Coastguard Worker 		break;
892*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450InterpolateAtCentroid:
893*03ce13f7SAndroid Build Coastguard Worker 		{
894*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.word(5));
895*03ce13f7SAndroid Build Coastguard Worker 			auto ptr = getPointer(insn.word(5));
896*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
897*03ce13f7SAndroid Build Coastguard Worker 			{
898*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, EmitInterpolate(ptr, d.Location, 0, i, Centroid));
899*03ce13f7SAndroid Build Coastguard Worker 			}
900*03ce13f7SAndroid Build Coastguard Worker 		}
901*03ce13f7SAndroid Build Coastguard Worker 		break;
902*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450InterpolateAtSample:
903*03ce13f7SAndroid Build Coastguard Worker 		{
904*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.word(5));
905*03ce13f7SAndroid Build Coastguard Worker 			auto ptr = getPointer(insn.word(5));
906*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
907*03ce13f7SAndroid Build Coastguard Worker 			{
908*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, EmitInterpolate(ptr, d.Location, insn.word(6), i, AtSample));
909*03ce13f7SAndroid Build Coastguard Worker 			}
910*03ce13f7SAndroid Build Coastguard Worker 		}
911*03ce13f7SAndroid Build Coastguard Worker 		break;
912*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450InterpolateAtOffset:
913*03ce13f7SAndroid Build Coastguard Worker 		{
914*03ce13f7SAndroid Build Coastguard Worker 			Spirv::Decorations d = shader.GetDecorationsForId(insn.word(5));
915*03ce13f7SAndroid Build Coastguard Worker 			auto ptr = getPointer(insn.word(5));
916*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
917*03ce13f7SAndroid Build Coastguard Worker 			{
918*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, EmitInterpolate(ptr, d.Location, insn.word(6), i, AtOffset));
919*03ce13f7SAndroid Build Coastguard Worker 			}
920*03ce13f7SAndroid Build Coastguard Worker 		}
921*03ce13f7SAndroid Build Coastguard Worker 		break;
922*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450NMin:
923*03ce13f7SAndroid Build Coastguard Worker 		{
924*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
925*03ce13f7SAndroid Build Coastguard Worker 			auto y = Operand(shader, *this, insn.word(6));
926*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
927*03ce13f7SAndroid Build Coastguard Worker 			{
928*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, NMin(x.Float(i), y.Float(i)));
929*03ce13f7SAndroid Build Coastguard Worker 			}
930*03ce13f7SAndroid Build Coastguard Worker 		}
931*03ce13f7SAndroid Build Coastguard Worker 		break;
932*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450NMax:
933*03ce13f7SAndroid Build Coastguard Worker 		{
934*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
935*03ce13f7SAndroid Build Coastguard Worker 			auto y = Operand(shader, *this, insn.word(6));
936*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
937*03ce13f7SAndroid Build Coastguard Worker 			{
938*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, NMax(x.Float(i), y.Float(i)));
939*03ce13f7SAndroid Build Coastguard Worker 			}
940*03ce13f7SAndroid Build Coastguard Worker 		}
941*03ce13f7SAndroid Build Coastguard Worker 		break;
942*03ce13f7SAndroid Build Coastguard Worker 	case GLSLstd450NClamp:
943*03ce13f7SAndroid Build Coastguard Worker 		{
944*03ce13f7SAndroid Build Coastguard Worker 			auto x = Operand(shader, *this, insn.word(5));
945*03ce13f7SAndroid Build Coastguard Worker 			auto minVal = Operand(shader, *this, insn.word(6));
946*03ce13f7SAndroid Build Coastguard Worker 			auto maxVal = Operand(shader, *this, insn.word(7));
947*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < type.componentCount; i++)
948*03ce13f7SAndroid Build Coastguard Worker 			{
949*03ce13f7SAndroid Build Coastguard Worker 				auto clamp = NMin(NMax(x.Float(i), minVal.Float(i)), maxVal.Float(i));
950*03ce13f7SAndroid Build Coastguard Worker 				dst.move(i, clamp);
951*03ce13f7SAndroid Build Coastguard Worker 			}
952*03ce13f7SAndroid Build Coastguard Worker 		}
953*03ce13f7SAndroid Build Coastguard Worker 		break;
954*03ce13f7SAndroid Build Coastguard Worker 	default:
955*03ce13f7SAndroid Build Coastguard Worker 		UNREACHABLE("ExtInst %d", int(extInstIndex));
956*03ce13f7SAndroid Build Coastguard Worker 		break;
957*03ce13f7SAndroid Build Coastguard Worker 	}
958*03ce13f7SAndroid Build Coastguard Worker }
959*03ce13f7SAndroid Build Coastguard Worker 
Interpolate(const SIMD::Float & x,const SIMD::Float & y,const SIMD::Float & rhw,const SIMD::Float & A,const SIMD::Float & B,const SIMD::Float & C,SpirvRoutine::Interpolation interpolation)960*03ce13f7SAndroid Build Coastguard Worker static SIMD::Float Interpolate(const SIMD::Float &x, const SIMD::Float &y, const SIMD::Float &rhw,
961*03ce13f7SAndroid Build Coastguard Worker                                const SIMD::Float &A, const SIMD::Float &B, const SIMD::Float &C,
962*03ce13f7SAndroid Build Coastguard Worker                                SpirvRoutine::Interpolation interpolation)
963*03ce13f7SAndroid Build Coastguard Worker {
964*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float interpolant = C;
965*03ce13f7SAndroid Build Coastguard Worker 
966*03ce13f7SAndroid Build Coastguard Worker 	if(interpolation != SpirvRoutine::Flat)
967*03ce13f7SAndroid Build Coastguard Worker 	{
968*03ce13f7SAndroid Build Coastguard Worker 		interpolant += x * A + y * B;
969*03ce13f7SAndroid Build Coastguard Worker 
970*03ce13f7SAndroid Build Coastguard Worker 		if(interpolation == SpirvRoutine::Perspective)
971*03ce13f7SAndroid Build Coastguard Worker 		{
972*03ce13f7SAndroid Build Coastguard Worker 			interpolant *= rhw;
973*03ce13f7SAndroid Build Coastguard Worker 		}
974*03ce13f7SAndroid Build Coastguard Worker 	}
975*03ce13f7SAndroid Build Coastguard Worker 
976*03ce13f7SAndroid Build Coastguard Worker 	return interpolant;
977*03ce13f7SAndroid Build Coastguard Worker }
978*03ce13f7SAndroid Build Coastguard Worker 
EmitInterpolate(const SIMD::Pointer & ptr,int32_t location,Spirv::Object::ID paramId,uint32_t component,InterpolationType type) const979*03ce13f7SAndroid Build Coastguard Worker SIMD::Float SpirvEmitter::EmitInterpolate(const SIMD::Pointer &ptr, int32_t location, Spirv::Object::ID paramId,
980*03ce13f7SAndroid Build Coastguard Worker                                           uint32_t component, InterpolationType type) const
981*03ce13f7SAndroid Build Coastguard Worker {
982*03ce13f7SAndroid Build Coastguard Worker 	uint32_t interpolant = (location * 4);
983*03ce13f7SAndroid Build Coastguard Worker 	uint32_t components_per_row = shader.GetNumInputComponents(location);
984*03ce13f7SAndroid Build Coastguard Worker 	if((location < 0) || (interpolant >= shader.inputs.size()) || (components_per_row == 0))
985*03ce13f7SAndroid Build Coastguard Worker 	{
986*03ce13f7SAndroid Build Coastguard Worker 		return SIMD::Float(0.0f);
987*03ce13f7SAndroid Build Coastguard Worker 	}
988*03ce13f7SAndroid Build Coastguard Worker 
989*03ce13f7SAndroid Build Coastguard Worker 	const auto &interpolationData = routine->interpolationData;
990*03ce13f7SAndroid Build Coastguard Worker 
991*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float x;
992*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float y;
993*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float rhw;
994*03ce13f7SAndroid Build Coastguard Worker 
995*03ce13f7SAndroid Build Coastguard Worker 	bool multisample = (multiSampleCount > 1);
996*03ce13f7SAndroid Build Coastguard Worker 	switch(type)
997*03ce13f7SAndroid Build Coastguard Worker 	{
998*03ce13f7SAndroid Build Coastguard Worker 	case Centroid:
999*03ce13f7SAndroid Build Coastguard Worker 		if(multisample)
1000*03ce13f7SAndroid Build Coastguard Worker 		{
1001*03ce13f7SAndroid Build Coastguard Worker 			x = interpolationData.xCentroid;
1002*03ce13f7SAndroid Build Coastguard Worker 			y = interpolationData.yCentroid;
1003*03ce13f7SAndroid Build Coastguard Worker 			rhw = interpolationData.rhwCentroid;
1004*03ce13f7SAndroid Build Coastguard Worker 		}
1005*03ce13f7SAndroid Build Coastguard Worker 		else
1006*03ce13f7SAndroid Build Coastguard Worker 		{
1007*03ce13f7SAndroid Build Coastguard Worker 			x = interpolationData.x;
1008*03ce13f7SAndroid Build Coastguard Worker 			y = interpolationData.y;
1009*03ce13f7SAndroid Build Coastguard Worker 			rhw = interpolationData.rhw;
1010*03ce13f7SAndroid Build Coastguard Worker 		}
1011*03ce13f7SAndroid Build Coastguard Worker 		break;
1012*03ce13f7SAndroid Build Coastguard Worker 	case AtSample:
1013*03ce13f7SAndroid Build Coastguard Worker 		x = SIMD::Float(0.0f);
1014*03ce13f7SAndroid Build Coastguard Worker 		y = SIMD::Float(0.0f);
1015*03ce13f7SAndroid Build Coastguard Worker 
1016*03ce13f7SAndroid Build Coastguard Worker 		if(multisample)
1017*03ce13f7SAndroid Build Coastguard Worker 		{
1018*03ce13f7SAndroid Build Coastguard Worker 			static constexpr int NUM_SAMPLES = 4;
1019*03ce13f7SAndroid Build Coastguard Worker 			ASSERT(multiSampleCount == NUM_SAMPLES);
1020*03ce13f7SAndroid Build Coastguard Worker 
1021*03ce13f7SAndroid Build Coastguard Worker 			auto sampleOperand = Operand(shader, *this, paramId);
1022*03ce13f7SAndroid Build Coastguard Worker 			ASSERT(sampleOperand.componentCount == 1);
1023*03ce13f7SAndroid Build Coastguard Worker 
1024*03ce13f7SAndroid Build Coastguard Worker 			// If sample does not exist, the position used to interpolate the
1025*03ce13f7SAndroid Build Coastguard Worker 			// input variable is undefined, so we just clamp to avoid OOB accesses.
1026*03ce13f7SAndroid Build Coastguard Worker 			SIMD::Int samples = sampleOperand.Int(0) & SIMD::Int(NUM_SAMPLES - 1);
1027*03ce13f7SAndroid Build Coastguard Worker 
1028*03ce13f7SAndroid Build Coastguard Worker 			for(int i = 0; i < SIMD::Width; i++)
1029*03ce13f7SAndroid Build Coastguard Worker 			{
1030*03ce13f7SAndroid Build Coastguard Worker 				Int sample = Extract(samples, i);
1031*03ce13f7SAndroid Build Coastguard Worker 				x = Insert(x, *Pointer<Float>(routine->constants + OFFSET(Constants, SampleLocationsX) + sample * sizeof(float)), i);
1032*03ce13f7SAndroid Build Coastguard Worker 				y = Insert(y, *Pointer<Float>(routine->constants + OFFSET(Constants, SampleLocationsY) + sample * sizeof(float)), i);
1033*03ce13f7SAndroid Build Coastguard Worker 			}
1034*03ce13f7SAndroid Build Coastguard Worker 		}
1035*03ce13f7SAndroid Build Coastguard Worker 
1036*03ce13f7SAndroid Build Coastguard Worker 		x += interpolationData.x;
1037*03ce13f7SAndroid Build Coastguard Worker 		y += interpolationData.y;
1038*03ce13f7SAndroid Build Coastguard Worker 		rhw = interpolationData.rhw;
1039*03ce13f7SAndroid Build Coastguard Worker 		break;
1040*03ce13f7SAndroid Build Coastguard Worker 	case AtOffset:
1041*03ce13f7SAndroid Build Coastguard Worker 		{
1042*03ce13f7SAndroid Build Coastguard Worker 			//  An offset of (0, 0) identifies the center of the pixel.
1043*03ce13f7SAndroid Build Coastguard Worker 			auto offset = Operand(shader, *this, paramId);
1044*03ce13f7SAndroid Build Coastguard Worker 			ASSERT(offset.componentCount == 2);
1045*03ce13f7SAndroid Build Coastguard Worker 
1046*03ce13f7SAndroid Build Coastguard Worker 			x = interpolationData.x + offset.Float(0);
1047*03ce13f7SAndroid Build Coastguard Worker 			y = interpolationData.y + offset.Float(1);
1048*03ce13f7SAndroid Build Coastguard Worker 			rhw = interpolationData.rhw;
1049*03ce13f7SAndroid Build Coastguard Worker 		}
1050*03ce13f7SAndroid Build Coastguard Worker 		break;
1051*03ce13f7SAndroid Build Coastguard Worker 	default:
1052*03ce13f7SAndroid Build Coastguard Worker 		UNREACHABLE("Unknown interpolation type: %d", (int)type);
1053*03ce13f7SAndroid Build Coastguard Worker 		return SIMD::Float(0.0f);
1054*03ce13f7SAndroid Build Coastguard Worker 	}
1055*03ce13f7SAndroid Build Coastguard Worker 
1056*03ce13f7SAndroid Build Coastguard Worker 	uint32_t packedInterpolant = shader.GetPackedInterpolant(location);
1057*03ce13f7SAndroid Build Coastguard Worker 	Pointer<Byte> planeEquation = interpolationData.primitive + OFFSET(Primitive, V[packedInterpolant]);
1058*03ce13f7SAndroid Build Coastguard Worker 
1059*03ce13f7SAndroid Build Coastguard Worker 	// The pointer's offsets index into the input variable array, which are SIMD::Float vectors.
1060*03ce13f7SAndroid Build Coastguard Worker 	// To obtain the index into the interpolant's plane equation we must unscale by the vector size.
1061*03ce13f7SAndroid Build Coastguard Worker 	const int offsetShift = log2i(sizeof(float) * SIMD::Width);
1062*03ce13f7SAndroid Build Coastguard Worker 
1063*03ce13f7SAndroid Build Coastguard Worker 	if(ptr.hasDynamicOffsets)
1064*03ce13f7SAndroid Build Coastguard Worker 	{
1065*03ce13f7SAndroid Build Coastguard Worker 		// Combine plane equations into one
1066*03ce13f7SAndroid Build Coastguard Worker 		SIMD::Float A;
1067*03ce13f7SAndroid Build Coastguard Worker 		SIMD::Float B;
1068*03ce13f7SAndroid Build Coastguard Worker 		SIMD::Float C;
1069*03ce13f7SAndroid Build Coastguard Worker 
1070*03ce13f7SAndroid Build Coastguard Worker 		for(int i = 0; i < SIMD::Width; i++)
1071*03ce13f7SAndroid Build Coastguard Worker 		{
1072*03ce13f7SAndroid Build Coastguard Worker 			Int offset = ((Extract(ptr.dynamicOffsets, i) + ptr.staticOffsets[i]) >> offsetShift) + component;
1073*03ce13f7SAndroid Build Coastguard Worker 			Pointer<Byte> planeEquationI = planeEquation + (offset * sizeof(PlaneEquation));
1074*03ce13f7SAndroid Build Coastguard Worker 			A = Insert(A, *Pointer<Float>(planeEquationI + OFFSET(PlaneEquation, A)), i);
1075*03ce13f7SAndroid Build Coastguard Worker 			B = Insert(B, *Pointer<Float>(planeEquationI + OFFSET(PlaneEquation, B)), i);
1076*03ce13f7SAndroid Build Coastguard Worker 			C = Insert(C, *Pointer<Float>(planeEquationI + OFFSET(PlaneEquation, C)), i);
1077*03ce13f7SAndroid Build Coastguard Worker 		}
1078*03ce13f7SAndroid Build Coastguard Worker 
1079*03ce13f7SAndroid Build Coastguard Worker 		return Interpolate(x, y, rhw, A, B, C, routine->inputsInterpolation[packedInterpolant]);
1080*03ce13f7SAndroid Build Coastguard Worker 	}
1081*03ce13f7SAndroid Build Coastguard Worker 	else
1082*03ce13f7SAndroid Build Coastguard Worker 	{
1083*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(ptr.hasStaticEqualOffsets());
1084*03ce13f7SAndroid Build Coastguard Worker 
1085*03ce13f7SAndroid Build Coastguard Worker 		uint32_t offset = (ptr.staticOffsets[0] >> offsetShift) + component;
1086*03ce13f7SAndroid Build Coastguard Worker 		if((interpolant + offset) >= shader.inputs.size())
1087*03ce13f7SAndroid Build Coastguard Worker 		{
1088*03ce13f7SAndroid Build Coastguard Worker 			return SIMD::Float(0.0f);
1089*03ce13f7SAndroid Build Coastguard Worker 		}
1090*03ce13f7SAndroid Build Coastguard Worker 		planeEquation += offset * sizeof(PlaneEquation);
1091*03ce13f7SAndroid Build Coastguard Worker 	}
1092*03ce13f7SAndroid Build Coastguard Worker 
1093*03ce13f7SAndroid Build Coastguard Worker 	return SpirvRoutine::interpolateAtXY(x, y, rhw, planeEquation, routine->inputsInterpolation[packedInterpolant]);
1094*03ce13f7SAndroid Build Coastguard Worker }
1095*03ce13f7SAndroid Build Coastguard Worker 
interpolateAtXY(const SIMD::Float & x,const SIMD::Float & y,const SIMD::Float & rhw,Pointer<Byte> planeEquation,Interpolation interpolation)1096*03ce13f7SAndroid Build Coastguard Worker SIMD::Float SpirvRoutine::interpolateAtXY(const SIMD::Float &x, const SIMD::Float &y, const SIMD::Float &rhw, Pointer<Byte> planeEquation, Interpolation interpolation)
1097*03ce13f7SAndroid Build Coastguard Worker {
1098*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float A;
1099*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float B;
1100*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float C = *Pointer<Float>(planeEquation + OFFSET(PlaneEquation, C));
1101*03ce13f7SAndroid Build Coastguard Worker 
1102*03ce13f7SAndroid Build Coastguard Worker 	if(interpolation != SpirvRoutine::Flat)
1103*03ce13f7SAndroid Build Coastguard Worker 	{
1104*03ce13f7SAndroid Build Coastguard Worker 		A = *Pointer<Float>(planeEquation + OFFSET(PlaneEquation, A));
1105*03ce13f7SAndroid Build Coastguard Worker 		B = *Pointer<Float>(planeEquation + OFFSET(PlaneEquation, B));
1106*03ce13f7SAndroid Build Coastguard Worker 	}
1107*03ce13f7SAndroid Build Coastguard Worker 
1108*03ce13f7SAndroid Build Coastguard Worker 	return Interpolate(x, y, rhw, A, B, C, interpolation);
1109*03ce13f7SAndroid Build Coastguard Worker }
1110*03ce13f7SAndroid Build Coastguard Worker 
1111*03ce13f7SAndroid Build Coastguard Worker }  // namespace sw
1112