blob: 3f8580079ab6b2e3467722357086385040c50e2f [file] [log] [blame]
Ben Clayton22f954e2019-11-28 10:54:23 +00001// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2//
3// 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
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// 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.
14
15#include "SpirvShader.hpp"
16
17#include "ShaderCore.hpp"
18
Ben Clayton22f954e2019-11-28 10:54:23 +000019#include <spirv/unified1/GLSL.std.450.h>
Ben Claytonbc1c0672019-12-17 20:37:37 +000020#include <spirv/unified1/spirv.hpp>
Ben Clayton22f954e2019-11-28 10:54:23 +000021
Ben Claytonbc1c0672019-12-17 20:37:37 +000022namespace {
23constexpr float PI = 3.141592653589793f;
Ben Clayton22f954e2019-11-28 10:54:23 +000024}
25
26namespace sw {
27
Ben Claytonb36dbbe2020-01-08 12:18:43 +000028SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitState *state) const
Ben Clayton22f954e2019-11-28 10:54:23 +000029{
Nicolas Capens71186752020-04-09 01:05:31 -040030 auto &type = getType(insn.resultTypeId());
Nicolas Capensff9f9b52020-04-14 00:46:38 -040031 auto &dst = state->createIntermediate(insn.resultId(), type.componentCount);
Ben Clayton22f954e2019-11-28 10:54:23 +000032 auto extInstIndex = static_cast<GLSLstd450>(insn.word(4));
33
Nicolas Capens81bc9d92019-12-16 15:05:57 -050034 switch(extInstIndex)
Ben Clayton22f954e2019-11-28 10:54:23 +000035 {
Ben Claytonbc1c0672019-12-17 20:37:37 +000036 case GLSLstd450FAbs:
Ben Clayton22f954e2019-11-28 10:54:23 +000037 {
Nicolas Capense6f65d92020-04-08 21:55:43 -040038 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -040039 for(auto i = 0u; i < type.componentCount; i++)
Ben Clayton22f954e2019-11-28 10:54:23 +000040 {
Ben Claytonbc1c0672019-12-17 20:37:37 +000041 dst.move(i, Abs(src.Float(i)));
Ben Clayton22f954e2019-11-28 10:54:23 +000042 }
Ben Claytonbc1c0672019-12-17 20:37:37 +000043 break;
Ben Clayton22f954e2019-11-28 10:54:23 +000044 }
Ben Claytonbc1c0672019-12-17 20:37:37 +000045 case GLSLstd450SAbs:
Ben Clayton22f954e2019-11-28 10:54:23 +000046 {
Nicolas Capense6f65d92020-04-08 21:55:43 -040047 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -040048 for(auto i = 0u; i < type.componentCount; i++)
Ben Clayton22f954e2019-11-28 10:54:23 +000049 {
Ben Claytonbc1c0672019-12-17 20:37:37 +000050 dst.move(i, Abs(src.Int(i)));
Ben Clayton22f954e2019-11-28 10:54:23 +000051 }
52 break;
53 }
Ben Claytonbc1c0672019-12-17 20:37:37 +000054 case GLSLstd450Cross:
Ben Clayton22f954e2019-11-28 10:54:23 +000055 {
Nicolas Capense6f65d92020-04-08 21:55:43 -040056 auto lhs = Operand(this, state, insn.word(5));
57 auto rhs = Operand(this, state, insn.word(6));
Ben Claytonbc1c0672019-12-17 20:37:37 +000058 dst.move(0, lhs.Float(1) * rhs.Float(2) - rhs.Float(1) * lhs.Float(2));
59 dst.move(1, lhs.Float(2) * rhs.Float(0) - rhs.Float(2) * lhs.Float(0));
60 dst.move(2, lhs.Float(0) * rhs.Float(1) - rhs.Float(0) * lhs.Float(1));
61 break;
62 }
63 case GLSLstd450Floor:
64 {
Nicolas Capense6f65d92020-04-08 21:55:43 -040065 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -040066 for(auto i = 0u; i < type.componentCount; i++)
Ben Clayton22f954e2019-11-28 10:54:23 +000067 {
Ben Claytonbc1c0672019-12-17 20:37:37 +000068 dst.move(i, Floor(src.Float(i)));
Ben Clayton22f954e2019-11-28 10:54:23 +000069 }
70 break;
71 }
Ben Claytonbc1c0672019-12-17 20:37:37 +000072 case GLSLstd450Trunc:
Ben Clayton22f954e2019-11-28 10:54:23 +000073 {
Nicolas Capense6f65d92020-04-08 21:55:43 -040074 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -040075 for(auto i = 0u; i < type.componentCount; i++)
Ben Clayton22f954e2019-11-28 10:54:23 +000076 {
Ben Claytonbc1c0672019-12-17 20:37:37 +000077 dst.move(i, Trunc(src.Float(i)));
78 }
79 break;
80 }
81 case GLSLstd450Ceil:
82 {
Nicolas Capense6f65d92020-04-08 21:55:43 -040083 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -040084 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +000085 {
86 dst.move(i, Ceil(src.Float(i)));
87 }
88 break;
89 }
90 case GLSLstd450Fract:
91 {
Nicolas Capense6f65d92020-04-08 21:55:43 -040092 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -040093 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +000094 {
95 dst.move(i, Frac(src.Float(i)));
96 }
97 break;
98 }
99 case GLSLstd450Round:
100 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400101 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400102 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000103 {
104 dst.move(i, Round(src.Float(i)));
105 }
106 break;
107 }
108 case GLSLstd450RoundEven:
109 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400110 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400111 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000112 {
113 auto x = Round(src.Float(i));
114 // dst = round(src) + ((round(src) < src) * 2 - 1) * (fract(src) == 0.5) * isOdd(round(src));
115 dst.move(i, x + ((SIMD::Float(CmpLT(x, src.Float(i)) & SIMD::Int(1)) * SIMD::Float(2.0f)) - SIMD::Float(1.0f)) *
116 SIMD::Float(CmpEQ(Frac(src.Float(i)), SIMD::Float(0.5f)) & SIMD::Int(1)) * SIMD::Float(Int4(x) & SIMD::Int(1)));
117 }
118 break;
119 }
120 case GLSLstd450FMin:
121 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400122 auto lhs = Operand(this, state, insn.word(5));
123 auto rhs = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400124 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000125 {
126 dst.move(i, Min(lhs.Float(i), rhs.Float(i)));
127 }
128 break;
129 }
130 case GLSLstd450FMax:
131 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400132 auto lhs = Operand(this, state, insn.word(5));
133 auto rhs = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400134 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000135 {
136 dst.move(i, Max(lhs.Float(i), rhs.Float(i)));
137 }
138 break;
139 }
140 case GLSLstd450SMin:
141 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400142 auto lhs = Operand(this, state, insn.word(5));
143 auto rhs = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400144 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000145 {
146 dst.move(i, Min(lhs.Int(i), rhs.Int(i)));
147 }
148 break;
149 }
150 case GLSLstd450SMax:
151 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400152 auto lhs = Operand(this, state, insn.word(5));
153 auto rhs = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400154 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000155 {
156 dst.move(i, Max(lhs.Int(i), rhs.Int(i)));
157 }
158 break;
159 }
160 case GLSLstd450UMin:
161 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400162 auto lhs = Operand(this, state, insn.word(5));
163 auto rhs = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400164 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000165 {
166 dst.move(i, Min(lhs.UInt(i), rhs.UInt(i)));
167 }
168 break;
169 }
170 case GLSLstd450UMax:
171 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400172 auto lhs = Operand(this, state, insn.word(5));
173 auto rhs = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400174 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000175 {
176 dst.move(i, Max(lhs.UInt(i), rhs.UInt(i)));
177 }
178 break;
179 }
180 case GLSLstd450Step:
181 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400182 auto edge = Operand(this, state, insn.word(5));
183 auto x = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400184 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000185 {
186 dst.move(i, CmpNLT(x.Float(i), edge.Float(i)) & As<SIMD::Int>(SIMD::Float(1.0f)));
187 }
188 break;
189 }
190 case GLSLstd450SmoothStep:
191 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400192 auto edge0 = Operand(this, state, insn.word(5));
193 auto edge1 = Operand(this, state, insn.word(6));
194 auto x = Operand(this, state, insn.word(7));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400195 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000196 {
197 auto tx = Min(Max((x.Float(i) - edge0.Float(i)) /
198 (edge1.Float(i) - edge0.Float(i)),
199 SIMD::Float(0.0f)),
200 SIMD::Float(1.0f));
201 dst.move(i, tx * tx * (Float4(3.0f) - Float4(2.0f) * tx));
202 }
203 break;
204 }
205 case GLSLstd450FMix:
206 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400207 auto x = Operand(this, state, insn.word(5));
208 auto y = Operand(this, state, insn.word(6));
209 auto a = Operand(this, state, insn.word(7));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400210 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000211 {
212 dst.move(i, a.Float(i) * (y.Float(i) - x.Float(i)) + x.Float(i));
213 }
214 break;
215 }
216 case GLSLstd450FClamp:
217 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400218 auto x = Operand(this, state, insn.word(5));
219 auto minVal = Operand(this, state, insn.word(6));
220 auto maxVal = Operand(this, state, insn.word(7));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400221 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000222 {
223 dst.move(i, Min(Max(x.Float(i), minVal.Float(i)), maxVal.Float(i)));
224 }
225 break;
226 }
227 case GLSLstd450SClamp:
228 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400229 auto x = Operand(this, state, insn.word(5));
230 auto minVal = Operand(this, state, insn.word(6));
231 auto maxVal = Operand(this, state, insn.word(7));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400232 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000233 {
234 dst.move(i, Min(Max(x.Int(i), minVal.Int(i)), maxVal.Int(i)));
235 }
236 break;
237 }
238 case GLSLstd450UClamp:
239 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400240 auto x = Operand(this, state, insn.word(5));
241 auto minVal = Operand(this, state, insn.word(6));
242 auto maxVal = Operand(this, state, insn.word(7));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400243 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000244 {
245 dst.move(i, Min(Max(x.UInt(i), minVal.UInt(i)), maxVal.UInt(i)));
246 }
247 break;
248 }
249 case GLSLstd450FSign:
250 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400251 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400252 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000253 {
254 auto neg = As<SIMD::Int>(CmpLT(src.Float(i), SIMD::Float(-0.0f))) & As<SIMD::Int>(SIMD::Float(-1.0f));
255 auto pos = As<SIMD::Int>(CmpNLE(src.Float(i), SIMD::Float(+0.0f))) & As<SIMD::Int>(SIMD::Float(1.0f));
256 dst.move(i, neg | pos);
257 }
258 break;
259 }
260 case GLSLstd450SSign:
261 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400262 auto src = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400263 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000264 {
265 auto neg = CmpLT(src.Int(i), SIMD::Int(0)) & SIMD::Int(-1);
266 auto pos = CmpNLE(src.Int(i), SIMD::Int(0)) & SIMD::Int(1);
267 dst.move(i, neg | pos);
268 }
269 break;
270 }
271 case GLSLstd450Reflect:
272 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400273 auto I = Operand(this, state, insn.word(5));
274 auto N = Operand(this, state, insn.word(6));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000275
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400276 SIMD::Float d = Dot(type.componentCount, I, N);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000277
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400278 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000279 {
280 dst.move(i, I.Float(i) - SIMD::Float(2.0f) * d * N.Float(i));
281 }
282 break;
283 }
284 case GLSLstd450Refract:
285 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400286 auto I = Operand(this, state, insn.word(5));
287 auto N = Operand(this, state, insn.word(6));
288 auto eta = Operand(this, state, insn.word(7));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000289
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400290 SIMD::Float d = Dot(type.componentCount, I, N);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000291 SIMD::Float k = SIMD::Float(1.0f) - eta.Float(0) * eta.Float(0) * (SIMD::Float(1.0f) - d * d);
292 SIMD::Int pos = CmpNLT(k, SIMD::Float(0.0f));
293 SIMD::Float t = (eta.Float(0) * d + Sqrt(k));
294
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400295 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000296 {
297 dst.move(i, pos & As<SIMD::Int>(eta.Float(0) * I.Float(i) - t * N.Float(i)));
298 }
299 break;
300 }
301 case GLSLstd450FaceForward:
302 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400303 auto N = Operand(this, state, insn.word(5));
304 auto I = Operand(this, state, insn.word(6));
305 auto Nref = Operand(this, state, insn.word(7));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000306
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400307 SIMD::Float d = Dot(type.componentCount, I, Nref);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000308 SIMD::Int neg = CmpLT(d, SIMD::Float(0.0f));
309
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400310 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000311 {
312 auto n = N.Float(i);
313 dst.move(i, (neg & As<SIMD::Int>(n)) | (~neg & As<SIMD::Int>(-n)));
314 }
315 break;
316 }
317 case GLSLstd450Length:
318 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400319 auto x = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400320 SIMD::Float d = Dot(getType(getObject(insn.word(5))).componentCount, x, x);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000321
322 dst.move(0, Sqrt(d));
323 break;
324 }
325 case GLSLstd450Normalize:
326 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400327 auto x = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400328 SIMD::Float d = Dot(getType(getObject(insn.word(5))).componentCount, x, x);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000329 SIMD::Float invLength = SIMD::Float(1.0f) / Sqrt(d);
330
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400331 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000332 {
333 dst.move(i, invLength * x.Float(i));
334 }
335 break;
336 }
337 case GLSLstd450Distance:
338 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400339 auto p0 = Operand(this, state, insn.word(5));
340 auto p1 = Operand(this, state, insn.word(6));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000341
342 // sqrt(dot(p0-p1, p0-p1))
343 SIMD::Float d = (p0.Float(0) - p1.Float(0)) * (p0.Float(0) - p1.Float(0));
344
Nicolas Capens2f4b6032020-04-09 02:01:50 -0400345 for(auto i = 1u; i < p0.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000346 {
347 d += (p0.Float(i) - p1.Float(i)) * (p0.Float(i) - p1.Float(i));
348 }
349
350 dst.move(0, Sqrt(d));
351 break;
352 }
353 case GLSLstd450Modf:
354 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400355 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000356 auto ptrId = Object::ID(insn.word(6));
Nicolas Capens20220a02020-04-09 02:48:16 -0400357
358 Intermediate whole(type.componentCount);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000359
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400360 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000361 {
Nicolas Capens20220a02020-04-09 02:48:16 -0400362 auto wholeAndFrac = Modf(val.Float(i));
363 dst.move(i, wholeAndFrac.second);
364 whole.move(i, wholeAndFrac.first);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000365 }
Nicolas Capens20220a02020-04-09 02:48:16 -0400366
367 Store(ptrId, whole, false, std::memory_order_relaxed, state);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000368 break;
369 }
370 case GLSLstd450ModfStruct:
371 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400372 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000373
Nicolas Capens2f4b6032020-04-09 02:01:50 -0400374 for(auto i = 0u; i < val.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000375 {
Nicolas Capens20220a02020-04-09 02:48:16 -0400376 auto wholeAndFrac = Modf(val.Float(i));
377 dst.move(i, wholeAndFrac.second);
378 dst.move(val.componentCount + i, wholeAndFrac.first);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000379 }
380 break;
381 }
382 case GLSLstd450PackSnorm4x8:
383 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400384 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000385 dst.move(0, (SIMD::Int(Round(Min(Max(val.Float(0), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(127.0f))) &
386 SIMD::Int(0xFF)) |
387 ((SIMD::Int(Round(Min(Max(val.Float(1), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(127.0f))) &
388 SIMD::Int(0xFF))
389 << 8) |
390 ((SIMD::Int(Round(Min(Max(val.Float(2), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(127.0f))) &
391 SIMD::Int(0xFF))
392 << 16) |
393 ((SIMD::Int(Round(Min(Max(val.Float(3), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(127.0f))) &
394 SIMD::Int(0xFF))
395 << 24));
396 break;
397 }
398 case GLSLstd450PackUnorm4x8:
399 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400400 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000401 dst.move(0, (SIMD::UInt(Round(Min(Max(val.Float(0), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(255.0f)))) |
402 ((SIMD::UInt(Round(Min(Max(val.Float(1), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(255.0f)))) << 8) |
403 ((SIMD::UInt(Round(Min(Max(val.Float(2), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(255.0f)))) << 16) |
404 ((SIMD::UInt(Round(Min(Max(val.Float(3), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(255.0f)))) << 24));
405 break;
406 }
407 case GLSLstd450PackSnorm2x16:
408 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400409 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000410 dst.move(0, (SIMD::Int(Round(Min(Max(val.Float(0), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(32767.0f))) &
411 SIMD::Int(0xFFFF)) |
412 ((SIMD::Int(Round(Min(Max(val.Float(1), SIMD::Float(-1.0f)), SIMD::Float(1.0f)) * SIMD::Float(32767.0f))) &
413 SIMD::Int(0xFFFF))
414 << 16));
415 break;
416 }
417 case GLSLstd450PackUnorm2x16:
418 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400419 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000420 dst.move(0, (SIMD::UInt(Round(Min(Max(val.Float(0), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(65535.0f))) &
421 SIMD::UInt(0xFFFF)) |
422 ((SIMD::UInt(Round(Min(Max(val.Float(1), SIMD::Float(0.0f)), SIMD::Float(1.0f)) * SIMD::Float(65535.0f))) &
423 SIMD::UInt(0xFFFF))
424 << 16));
425 break;
426 }
427 case GLSLstd450PackHalf2x16:
428 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400429 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000430 dst.move(0, floatToHalfBits(val.UInt(0), false) | floatToHalfBits(val.UInt(1), true));
431 break;
432 }
433 case GLSLstd450UnpackSnorm4x8:
434 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400435 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000436 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)));
437 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)));
438 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)));
439 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)));
440 break;
441 }
442 case GLSLstd450UnpackUnorm4x8:
443 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400444 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000445 dst.move(0, SIMD::Float((val.UInt(0) & SIMD::UInt(0xFF))) * SIMD::Float(1.0f / 255.f));
446 dst.move(1, SIMD::Float(((val.UInt(0) >> 8) & SIMD::UInt(0xFF))) * SIMD::Float(1.0f / 255.f));
447 dst.move(2, SIMD::Float(((val.UInt(0) >> 16) & SIMD::UInt(0xFF))) * SIMD::Float(1.0f / 255.f));
448 dst.move(3, SIMD::Float(((val.UInt(0) >> 24) & SIMD::UInt(0xFF))) * SIMD::Float(1.0f / 255.f));
449 break;
450 }
451 case GLSLstd450UnpackSnorm2x16:
452 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400453 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000454 // clamp(f / 32767.0, -1.0, 1.0)
455 dst.move(0, Min(Max(SIMD::Float(As<SIMD::Int>((val.UInt(0) & SIMD::UInt(0x0000FFFF)) << 16)) *
456 SIMD::Float(1.0f / float(0x7FFF0000)),
457 SIMD::Float(-1.0f)),
458 SIMD::Float(1.0f)));
459 dst.move(1, Min(Max(SIMD::Float(As<SIMD::Int>(val.UInt(0) & SIMD::UInt(0xFFFF0000))) * SIMD::Float(1.0f / float(0x7FFF0000)),
460 SIMD::Float(-1.0f)),
461 SIMD::Float(1.0f)));
462 break;
463 }
464 case GLSLstd450UnpackUnorm2x16:
465 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400466 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000467 // f / 65535.0
468 dst.move(0, SIMD::Float((val.UInt(0) & SIMD::UInt(0x0000FFFF)) << 16) * SIMD::Float(1.0f / float(0xFFFF0000)));
469 dst.move(1, SIMD::Float(val.UInt(0) & SIMD::UInt(0xFFFF0000)) * SIMD::Float(1.0f / float(0xFFFF0000)));
470 break;
471 }
472 case GLSLstd450UnpackHalf2x16:
473 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400474 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000475 dst.move(0, halfToFloatBits(val.UInt(0) & SIMD::UInt(0x0000FFFF)));
476 dst.move(1, halfToFloatBits((val.UInt(0) & SIMD::UInt(0xFFFF0000)) >> 16));
477 break;
478 }
479 case GLSLstd450Fma:
480 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400481 auto a = Operand(this, state, insn.word(5));
482 auto b = Operand(this, state, insn.word(6));
483 auto c = Operand(this, state, insn.word(7));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400484 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000485 {
486 dst.move(i, FMA(a.Float(i), b.Float(i), c.Float(i)));
487 }
488 break;
489 }
490 case GLSLstd450Frexp:
491 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400492 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000493 auto ptrId = Object::ID(insn.word(6));
Nicolas Capens20220a02020-04-09 02:48:16 -0400494
495 Intermediate exp(type.componentCount);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000496
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400497 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000498 {
Nicolas Capens20220a02020-04-09 02:48:16 -0400499 auto significandAndExponent = Frexp(val.Float(i));
500 dst.move(i, significandAndExponent.first);
501 exp.move(i, significandAndExponent.second);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000502 }
Nicolas Capens20220a02020-04-09 02:48:16 -0400503
504 Store(ptrId, exp, false, std::memory_order_relaxed, state);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000505 break;
506 }
507 case GLSLstd450FrexpStruct:
508 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400509 auto val = Operand(this, state, insn.word(5));
Nicolas Capens2f4b6032020-04-09 02:01:50 -0400510
511 for(auto i = 0u; i < val.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000512 {
513 auto significandAndExponent = Frexp(val.Float(i));
514 dst.move(i, significandAndExponent.first);
Nicolas Capens2f4b6032020-04-09 02:01:50 -0400515 dst.move(val.componentCount + i, significandAndExponent.second);
Ben Claytonbc1c0672019-12-17 20:37:37 +0000516 }
517 break;
518 }
519 case GLSLstd450Ldexp:
520 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400521 auto significand = Operand(this, state, insn.word(5));
522 auto exponent = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400523 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000524 {
525 // Assumes IEEE 754
526 auto in = significand.Float(i);
527 auto significandExponent = Exponent(in);
528 auto combinedExponent = exponent.Int(i) + significandExponent;
529 auto isSignificandZero = SIMD::UInt(CmpEQ(significand.Int(i), SIMD::Int(0)));
530 auto isSignificandInf = SIMD::UInt(IsInf(in));
531 auto isSignificandNaN = SIMD::UInt(IsNan(in));
532 auto isExponentNotTooSmall = SIMD::UInt(CmpGE(combinedExponent, SIMD::Int(-126)));
533 auto isExponentNotTooLarge = SIMD::UInt(CmpLE(combinedExponent, SIMD::Int(128)));
534 auto isExponentInBounds = isExponentNotTooSmall & isExponentNotTooLarge;
535
536 SIMD::UInt v;
537 v = significand.UInt(i) & SIMD::UInt(0x7FFFFF); // Add significand.
538 v |= (SIMD::UInt(combinedExponent + SIMD::Int(126)) << SIMD::UInt(23)); // Add exponent.
539 v &= isExponentInBounds; // Clear v if the exponent is OOB.
540
541 v |= significand.UInt(i) & SIMD::UInt(0x80000000); // Add sign bit.
542 v |= ~isExponentNotTooLarge & SIMD::UInt(0x7F800000); // Mark as inf if the exponent is too great.
543
544 // If the input significand is zero, inf or nan, just return the
545 // input significand.
546 auto passthrough = isSignificandZero | isSignificandInf | isSignificandNaN;
547 v = (v & ~passthrough) | (significand.UInt(i) & passthrough);
548
549 dst.move(i, As<SIMD::Float>(v));
550 }
551 break;
552 }
553 case GLSLstd450Radians:
554 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400555 auto degrees = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400556 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000557 {
558 dst.move(i, degrees.Float(i) * SIMD::Float(PI / 180.0f));
559 }
560 break;
561 }
562 case GLSLstd450Degrees:
563 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400564 auto radians = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400565 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000566 {
567 dst.move(i, radians.Float(i) * SIMD::Float(180.0f / PI));
568 }
569 break;
570 }
571 case GLSLstd450Sin:
572 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400573 auto radians = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400574 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000575 {
576 dst.move(i, Sin(radians.Float(i)));
577 }
578 break;
579 }
580 case GLSLstd450Cos:
581 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400582 auto radians = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400583 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000584 {
585 dst.move(i, Cos(radians.Float(i)));
586 }
587 break;
588 }
589 case GLSLstd450Tan:
590 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400591 auto radians = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400592 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000593 {
594 dst.move(i, Tan(radians.Float(i)));
595 }
596 break;
597 }
598 case GLSLstd450Asin:
599 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400600 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400601 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000602 {
603 dst.move(i, Asin(val.Float(i)));
604 }
605 break;
606 }
607 case GLSLstd450Acos:
608 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400609 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400610 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000611 {
612 dst.move(i, Acos(val.Float(i)));
613 }
614 break;
615 }
616 case GLSLstd450Atan:
617 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400618 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400619 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000620 {
621 dst.move(i, Atan(val.Float(i)));
622 }
623 break;
624 }
625 case GLSLstd450Sinh:
626 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400627 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400628 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000629 {
630 dst.move(i, Sinh(val.Float(i)));
631 }
632 break;
633 }
634 case GLSLstd450Cosh:
635 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400636 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400637 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000638 {
639 dst.move(i, Cosh(val.Float(i)));
640 }
641 break;
642 }
643 case GLSLstd450Tanh:
644 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400645 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400646 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000647 {
648 dst.move(i, Tanh(val.Float(i)));
649 }
650 break;
651 }
652 case GLSLstd450Asinh:
653 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400654 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400655 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000656 {
657 dst.move(i, Asinh(val.Float(i)));
658 }
659 break;
660 }
661 case GLSLstd450Acosh:
662 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400663 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400664 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000665 {
666 dst.move(i, Acosh(val.Float(i)));
667 }
668 break;
669 }
670 case GLSLstd450Atanh:
671 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400672 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400673 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000674 {
675 dst.move(i, Atanh(val.Float(i)));
676 }
677 break;
678 }
679 case GLSLstd450Atan2:
680 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400681 auto x = Operand(this, state, insn.word(5));
682 auto y = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400683 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000684 {
685 dst.move(i, Atan2(x.Float(i), y.Float(i)));
686 }
687 break;
688 }
689 case GLSLstd450Pow:
690 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400691 auto x = Operand(this, state, insn.word(5));
692 auto y = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400693 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000694 {
695 dst.move(i, Pow(x.Float(i), y.Float(i)));
696 }
697 break;
698 }
699 case GLSLstd450Exp:
700 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400701 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400702 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000703 {
704 dst.move(i, Exp(val.Float(i)));
705 }
706 break;
707 }
708 case GLSLstd450Log:
709 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400710 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400711 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000712 {
713 dst.move(i, Log(val.Float(i)));
714 }
715 break;
716 }
717 case GLSLstd450Exp2:
718 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400719 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400720 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000721 {
722 dst.move(i, Exp2(val.Float(i)));
723 }
724 break;
725 }
726 case GLSLstd450Log2:
727 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400728 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400729 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000730 {
731 dst.move(i, Log2(val.Float(i)));
732 }
733 break;
734 }
735 case GLSLstd450Sqrt:
736 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400737 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400738 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000739 {
740 dst.move(i, Sqrt(val.Float(i)));
741 }
742 break;
743 }
744 case GLSLstd450InverseSqrt:
745 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400746 auto val = Operand(this, state, insn.word(5));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000747 Decorations d;
748 ApplyDecorationsForId(&d, insn.word(5));
749 if(d.RelaxedPrecision)
750 {
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400751 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000752 {
753 dst.move(i, RcpSqrt_pp(val.Float(i)));
754 }
755 }
756 else
757 {
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400758 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000759 {
760 dst.move(i, SIMD::Float(1.0f) / Sqrt(val.Float(i)));
761 }
762 }
763 break;
764 }
765 case GLSLstd450Determinant:
766 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400767 auto mat = Operand(this, state, insn.word(5));
Nicolas Capens2f4b6032020-04-09 02:01:50 -0400768
769 switch(mat.componentCount)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000770 {
771 case 4: // 2x2
772 dst.move(0, Determinant(
773 mat.Float(0), mat.Float(1),
774 mat.Float(2), mat.Float(3)));
775 break;
776 case 9: // 3x3
777 dst.move(0, Determinant(
778 mat.Float(0), mat.Float(1), mat.Float(2),
779 mat.Float(3), mat.Float(4), mat.Float(5),
780 mat.Float(6), mat.Float(7), mat.Float(8)));
781 break;
782 case 16: // 4x4
783 dst.move(0, Determinant(
784 mat.Float(0), mat.Float(1), mat.Float(2), mat.Float(3),
785 mat.Float(4), mat.Float(5), mat.Float(6), mat.Float(7),
786 mat.Float(8), mat.Float(9), mat.Float(10), mat.Float(11),
787 mat.Float(12), mat.Float(13), mat.Float(14), mat.Float(15)));
788 break;
789 default:
Nicolas Capens2f4b6032020-04-09 02:01:50 -0400790 UNREACHABLE("GLSLstd450Determinant can only operate with square matrices. Got %d elements", int(mat.componentCount));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000791 }
792 break;
793 }
794 case GLSLstd450MatrixInverse:
795 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400796 auto mat = Operand(this, state, insn.word(5));
Nicolas Capens2f4b6032020-04-09 02:01:50 -0400797
798 switch(mat.componentCount)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000799 {
800 case 4: // 2x2
801 {
802 auto inv = MatrixInverse(
803 mat.Float(0), mat.Float(1),
804 mat.Float(2), mat.Float(3));
805 for(uint32_t i = 0; i < inv.size(); i++)
806 {
807 dst.move(i, inv[i]);
808 }
809 break;
810 }
811 case 9: // 3x3
812 {
813 auto inv = MatrixInverse(
814 mat.Float(0), mat.Float(1), mat.Float(2),
815 mat.Float(3), mat.Float(4), mat.Float(5),
816 mat.Float(6), mat.Float(7), mat.Float(8));
817 for(uint32_t i = 0; i < inv.size(); i++)
818 {
819 dst.move(i, inv[i]);
820 }
821 break;
822 }
823 case 16: // 4x4
824 {
825 auto inv = MatrixInverse(
826 mat.Float(0), mat.Float(1), mat.Float(2), mat.Float(3),
827 mat.Float(4), mat.Float(5), mat.Float(6), mat.Float(7),
828 mat.Float(8), mat.Float(9), mat.Float(10), mat.Float(11),
829 mat.Float(12), mat.Float(13), mat.Float(14), mat.Float(15));
830 for(uint32_t i = 0; i < inv.size(); i++)
831 {
832 dst.move(i, inv[i]);
833 }
834 break;
835 }
836 default:
Nicolas Capens2f4b6032020-04-09 02:01:50 -0400837 UNREACHABLE("GLSLstd450MatrixInverse can only operate with square matrices. Got %d elements", int(mat.componentCount));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000838 }
839 break;
840 }
841 case GLSLstd450IMix:
842 {
843 UNREACHABLE("GLSLstd450IMix has been removed from the specification");
844 break;
845 }
846 case GLSLstd450PackDouble2x32:
847 {
848 UNSUPPORTED("SPIR-V Float64 Capability (GLSLstd450PackDouble2x32)");
849 break;
850 }
851 case GLSLstd450UnpackDouble2x32:
852 {
853 UNSUPPORTED("SPIR-V Float64 Capability (GLSLstd450UnpackDouble2x32)");
854 break;
855 }
856 case GLSLstd450FindILsb:
857 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400858 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400859 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000860 {
861 auto v = val.UInt(i);
862 dst.move(i, Cttz(v, true) | CmpEQ(v, SIMD::UInt(0)));
863 }
864 break;
865 }
866 case GLSLstd450FindSMsb:
867 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400868 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400869 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000870 {
871 auto v = val.UInt(i) ^ As<SIMD::UInt>(CmpLT(val.Int(i), SIMD::Int(0)));
872 dst.move(i, SIMD::UInt(31) - Ctlz(v, false));
873 }
874 break;
875 }
876 case GLSLstd450FindUMsb:
877 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400878 auto val = Operand(this, state, insn.word(5));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400879 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000880 {
881 dst.move(i, SIMD::UInt(31) - Ctlz(val.UInt(i), false));
882 }
883 break;
884 }
885 case GLSLstd450InterpolateAtCentroid:
886 {
887 UNSUPPORTED("SPIR-V SampleRateShading Capability (GLSLstd450InterpolateAtCentroid)");
888 break;
889 }
890 case GLSLstd450InterpolateAtSample:
891 {
892 UNSUPPORTED("SPIR-V SampleRateShading Capability (GLSLstd450InterpolateAtCentroid)");
893 break;
894 }
895 case GLSLstd450InterpolateAtOffset:
896 {
897 UNSUPPORTED("SPIR-V SampleRateShading Capability (GLSLstd450InterpolateAtCentroid)");
898 break;
899 }
900 case GLSLstd450NMin:
901 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400902 auto x = Operand(this, state, insn.word(5));
903 auto y = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400904 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000905 {
906 dst.move(i, NMin(x.Float(i), y.Float(i)));
907 }
908 break;
909 }
910 case GLSLstd450NMax:
911 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400912 auto x = Operand(this, state, insn.word(5));
913 auto y = Operand(this, state, insn.word(6));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400914 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000915 {
916 dst.move(i, NMax(x.Float(i), y.Float(i)));
917 }
918 break;
919 }
920 case GLSLstd450NClamp:
921 {
Nicolas Capense6f65d92020-04-08 21:55:43 -0400922 auto x = Operand(this, state, insn.word(5));
923 auto minVal = Operand(this, state, insn.word(6));
924 auto maxVal = Operand(this, state, insn.word(7));
Nicolas Capensff9f9b52020-04-14 00:46:38 -0400925 for(auto i = 0u; i < type.componentCount; i++)
Ben Claytonbc1c0672019-12-17 20:37:37 +0000926 {
927 auto clamp = NMin(NMax(x.Float(i), minVal.Float(i)), maxVal.Float(i));
928 dst.move(i, clamp);
Ben Clayton22f954e2019-11-28 10:54:23 +0000929 }
930 break;
931 }
932 default:
Ben Claytonbc1c0672019-12-17 20:37:37 +0000933 UNREACHABLE("ExtInst %d", int(extInstIndex));
934 break;
Ben Clayton22f954e2019-11-28 10:54:23 +0000935 }
936
937 return EmitResult::Continue;
938}
939
940} // namespace sw