• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 "SetupRoutine.hpp"
16 
17 #include "Constants.hpp"
18 #include "Device/Polygon.hpp"
19 #include "Device/Primitive.hpp"
20 #include "Device/Renderer.hpp"
21 #include "Device/Vertex.hpp"
22 #include "Reactor/Reactor.hpp"
23 #include "Vulkan/VkDevice.hpp"
24 
25 namespace sw {
26 
SetupRoutine(const SetupProcessor::State & state)27 SetupRoutine::SetupRoutine(const SetupProcessor::State &state)
28     : state(state)
29 {
30 }
31 
~SetupRoutine()32 SetupRoutine::~SetupRoutine()
33 {
34 }
35 
generate()36 void SetupRoutine::generate()
37 {
38 	SetupFunction function;
39 	{
40 		Pointer<Byte> device(function.Arg<0>());
41 		Pointer<Byte> primitive(function.Arg<1>());
42 		Pointer<Byte> tri(function.Arg<2>());
43 		Pointer<Byte> polygon(function.Arg<3>());
44 		Pointer<Byte> data(function.Arg<4>());
45 
46 		Pointer<Byte> constants = device + OFFSET(vk::Device, constants);
47 
48 		const bool point = state.isDrawPoint;
49 		const bool line = state.isDrawLine;
50 		const bool triangle = state.isDrawTriangle;
51 
52 		const int V0 = OFFSET(Triangle, v0);
53 		const int V1 = (triangle || line) ? OFFSET(Triangle, v1) : OFFSET(Triangle, v0);
54 		const int V2 = triangle ? OFFSET(Triangle, v2) : (line ? OFFSET(Triangle, v1) : OFFSET(Triangle, v0));
55 
56 		Pointer<Byte> v0 = tri + V0;
57 		Pointer<Byte> v1 = tri + V1;
58 		Pointer<Byte> v2 = tri + V2;
59 
60 		Array<Int> X(16);
61 		Array<Int> Y(16);
62 
63 		X[0] = *Pointer<Int>(v0 + OFFSET(Vertex, projected.x));
64 		X[1] = *Pointer<Int>(v1 + OFFSET(Vertex, projected.x));
65 		X[2] = *Pointer<Int>(v2 + OFFSET(Vertex, projected.x));
66 
67 		Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex, projected.y));
68 		Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex, projected.y));
69 		Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex, projected.y));
70 
71 		Int d = 1;  // Winding direction
72 
73 		// Culling
74 		if(triangle)
75 		{
76 			Float x0 = Float(X[0]);
77 			Float x1 = Float(X[1]);
78 			Float x2 = Float(X[2]);
79 
80 			Float y0 = Float(Y[0]);
81 			Float y1 = Float(Y[1]);
82 			Float y2 = Float(Y[2]);
83 
84 			Float A = (y0 - y2) * x1 + (y2 - y1) * x0 + (y1 - y0) * x2;  // Area
85 
86 			Int w0w1w2 = *Pointer<Int>(v0 + OFFSET(Vertex, w)) ^
87 			             *Pointer<Int>(v1 + OFFSET(Vertex, w)) ^
88 			             *Pointer<Int>(v2 + OFFSET(Vertex, w));
89 
90 			A = IfThenElse(w0w1w2 < 0, -A, A);
91 
92 			Bool frontFacing = (state.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE) ? (A >= 0.0f) : (A <= 0.0f);
93 
94 			if(state.cullMode & VK_CULL_MODE_FRONT_BIT)
95 			{
96 				If(frontFacing) Return(0);
97 			}
98 			if(state.cullMode & VK_CULL_MODE_BACK_BIT)
99 			{
100 				If(!frontFacing) Return(0);
101 			}
102 
103 			d = IfThenElse(A > 0.0f, d, Int(0));
104 
105 			If(frontFacing)
106 			{
107 				*Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
108 				*Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
109 			}
110 			Else
111 			{
112 				*Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
113 				*Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
114 			}
115 		}
116 		else
117 		{
118 			*Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
119 			*Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
120 		}
121 
122 		Int n = *Pointer<Int>(polygon + OFFSET(Polygon, n));
123 		Int m = *Pointer<Int>(polygon + OFFSET(Polygon, i));
124 
125 		If(m != 0 || Bool(!triangle))  // Clipped triangle; reproject
126 		{
127 			Pointer<Byte> V = polygon + OFFSET(Polygon, P) + m * sizeof(void *) * 16;
128 
129 			Int i = 0;
130 
131 			Do
132 			{
133 				Pointer<Float4> p = *Pointer<Pointer<Float4> >(V + i * sizeof(void *));
134 				Float4 v = *Pointer<Float4>(p, 16);
135 
136 				Float w = v.w;
137 				Float rhw = IfThenElse(w != 0.0f, 1.0f / w, Float(1.0f));
138 
139 				X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData, X0xF)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData, WxF)));
140 				Y[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData, Y0xF)) + v.y * rhw * *Pointer<Float>(data + OFFSET(DrawData, HxF)));
141 
142 				i++;
143 			}
144 			Until(i >= n);
145 		}
146 
147 		// Vertical range
148 		Int yMin = Y[0];
149 		Int yMax = Y[0];
150 
151 		Int i = 1;
152 
153 		Do
154 		{
155 			yMin = Min(Y[i], yMin);
156 			yMax = Max(Y[i], yMax);
157 
158 			i++;
159 		}
160 		Until(i >= n);
161 
162 		constexpr int subPixB = vk::SUBPIXEL_PRECISION_BITS;
163 		constexpr int subPixM = vk::SUBPIXEL_PRECISION_MASK;
164 		constexpr float subPixF = vk::SUBPIXEL_PRECISION_FACTOR;
165 
166 		if(state.enableMultiSampling)
167 		{
168 			yMin = (yMin + Constants::yMinMultiSampleOffset) >> subPixB;
169 			yMax = (yMax + Constants::yMaxMultiSampleOffset) >> subPixB;
170 		}
171 		else
172 		{
173 			yMin = (yMin + subPixM) >> subPixB;
174 			yMax = (yMax + subPixM) >> subPixB;
175 		}
176 
177 		yMin = Max(yMin, *Pointer<Int>(data + OFFSET(DrawData, scissorY0)));
178 		yMax = Min(yMax, *Pointer<Int>(data + OFFSET(DrawData, scissorY1)));
179 
180 		// If yMin and yMax are initially negative, the scissor clamping above will typically result
181 		// in yMin == 0 and yMax unchanged. We bail as we don't need to rasterize this primitive, and
182 		// code below assumes yMin < yMax.
183 		If(yMin >= yMax)
184 		{
185 			Return(0);
186 		}
187 
188 		For(Int q = 0, q < state.multiSampleCount, q++)
189 		{
190 			Array<Int> Xq(16);
191 			Array<Int> Yq(16);
192 
193 			Int i = 0;
194 
195 			Do
196 			{
197 				Xq[i] = X[i];
198 				Yq[i] = Y[i];
199 
200 				if(state.enableMultiSampling)
201 				{
202 					// The subtraction here is because we're not moving the point, we're testing the edge against it
203 					Xq[i] = Xq[i] - *Pointer<Int>(constants + OFFSET(Constants, Xf) + q * sizeof(int));
204 					Yq[i] = Yq[i] - *Pointer<Int>(constants + OFFSET(Constants, Yf) + q * sizeof(int));
205 				}
206 
207 				i++;
208 			}
209 			Until(i >= n);
210 
211 			Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive, outline->left)) + q * sizeof(Primitive);
212 			Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive, outline->right)) + q * sizeof(Primitive);
213 
214 			if(state.enableMultiSampling)
215 			{
216 				Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0));
217 				Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1));
218 				Short x = Short(Clamp((X[0] + subPixM) >> subPixB, xMin, xMax));
219 
220 				For(Int y = yMin - 1, y < yMax + 1, y++)
221 				{
222 					*Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x;
223 					*Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x;
224 				}
225 			}
226 
227 			Xq[n] = Xq[0];
228 			Yq[n] = Yq[0];
229 
230 			// Rasterize
231 			{
232 				Int i = 0;
233 
234 				Do
235 				{
236 					edge(primitive, data, Xq[i + 1 - d], Yq[i + 1 - d], Xq[i + d], Yq[i + d], q);
237 
238 					i++;
239 				}
240 				Until(i >= n);
241 			}
242 
243 			if(!state.enableMultiSampling)
244 			{
245 				For(, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++)
246 				{
247 					// Increments yMin
248 				}
249 
250 				For(, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--)
251 				{
252 					// Decrements yMax
253 				}
254 
255 				If(yMin == yMax)
256 				{
257 					Return(0);
258 				}
259 
260 				*Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
261 				*Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
262 				*Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
263 				*Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
264 			}
265 		}
266 
267 		*Pointer<Int>(primitive + OFFSET(Primitive, yMin)) = yMin;
268 		*Pointer<Int>(primitive + OFFSET(Primitive, yMax)) = yMax;
269 
270 		// Sort by minimum y
271 		if(triangle)
272 		{
273 			Float y0 = *Pointer<Float>(v0 + OFFSET(Vertex, y));
274 			Float y1 = *Pointer<Float>(v1 + OFFSET(Vertex, y));
275 			Float y2 = *Pointer<Float>(v2 + OFFSET(Vertex, y));
276 
277 			Float yMin = Min(Min(y0, y1), y2);
278 
279 			conditionalRotate1(yMin == y1, v0, v1, v2);
280 			conditionalRotate2(yMin == y2, v0, v1, v2);
281 		}
282 
283 		// Sort by maximum w
284 		if(triangle)
285 		{
286 			Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, w));
287 			Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, w));
288 			Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, w));
289 
290 			Float wMax = Max(Max(w0, w1), w2);
291 
292 			conditionalRotate1(wMax == w1, v0, v1, v2);
293 			conditionalRotate2(wMax == w2, v0, v1, v2);
294 		}
295 
296 		Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, w));
297 		Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, w));
298 		Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, w));
299 
300 		Float4 w012;
301 
302 		w012.x = w0;
303 		w012.y = w1;
304 		w012.z = w2;
305 		w012.w = 1;
306 
307 		Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex, projected.w));
308 
309 		Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex, projected.x));
310 		Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex, projected.x));
311 		Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex, projected.x));
312 
313 		Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex, projected.y));
314 		Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex, projected.y));
315 		Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex, projected.y));
316 
317 		if(point)
318 		{
319 			*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordX)) = Float(1.0f / subPixF) * Float(X0);
320 			*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordY)) = Float(1.0f / subPixF) * Float(Y0);
321 		}
322 
323 		if(line)
324 		{
325 			X2 = X1 + Y1 - Y0;
326 			Y2 = Y1 + X0 - X1;
327 		}
328 
329 		Float dx = Float(X0) * (1.0f / subPixF);
330 		Float dy = Float(Y0) * (1.0f / subPixF);
331 
332 		X1 -= X0;
333 		Y1 -= Y0;
334 
335 		X2 -= X0;
336 		Y2 -= Y0;
337 
338 		Float x1 = w1 * (1.0f / subPixF) * Float(X1);
339 		Float y1 = w1 * (1.0f / subPixF) * Float(Y1);
340 
341 		Float x2 = w2 * (1.0f / subPixF) * Float(X2);
342 		Float y2 = w2 * (1.0f / subPixF) * Float(Y2);
343 
344 		Float a = x1 * y2 - x2 * y1;
345 
346 		Float4 xQuad = Float4(0, 1, 0, 1) - Float4(dx);
347 		Float4 yQuad = Float4(0, 0, 1, 1) - Float4(dy);
348 
349 		*Pointer<Float4>(primitive + OFFSET(Primitive, xQuad), 16) = xQuad;
350 		*Pointer<Float4>(primitive + OFFSET(Primitive, yQuad), 16) = yQuad;
351 
352 		Float4 M[3];
353 
354 		M[0] = Float4(0, 0, 0, 0);
355 		M[1] = Float4(0, 0, 0, 0);
356 		M[2] = Float4(0, 0, 0, 0);
357 
358 		M[0].z = rhw0;
359 
360 		If(a != 0.0f)
361 		{
362 			Float A = 1.0f / a;
363 			Float D = A * rhw0;
364 
365 			M[0].x = (y1 * w2 - y2 * w1) * D;
366 			M[0].y = (x2 * w1 - x1 * w2) * D;
367 			//	M[0].z = rhw0;
368 			//	M[0].w = 0;
369 
370 			M[1].x = y2 * A;
371 			M[1].y = -x2 * A;
372 			//	M[1].z = 0;
373 			//	M[1].w = 0;
374 
375 			M[2].x = -y1 * A;
376 			M[2].y = x1 * A;
377 			//	M[2].z = 0;
378 			//	M[2].w = 0;
379 		}
380 
381 		if(state.interpolateW)
382 		{
383 			Float4 ABC = M[0] + M[1] + M[2];
384 
385 			Float4 A = ABC.x;
386 			Float4 B = ABC.y;
387 			Float4 C = ABC.z;
388 
389 			*Pointer<Float4>(primitive + OFFSET(Primitive, w.A), 16) = A;
390 			*Pointer<Float4>(primitive + OFFSET(Primitive, w.B), 16) = B;
391 			*Pointer<Float4>(primitive + OFFSET(Primitive, w.C), 16) = C;
392 		}
393 
394 		if(state.interpolateZ)
395 		{
396 			Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex, projected.z));
397 			Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex, projected.z));
398 			Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex, projected.z));
399 
400 			z1 -= z0;
401 			z2 -= z0;
402 
403 			Float A;
404 			Float B;
405 			Float C;
406 
407 			if(!point)
408 			{
409 				Float x1 = Float(X1) * (1.0f / subPixF);
410 				Float y1 = Float(Y1) * (1.0f / subPixF);
411 				Float x2 = Float(X2) * (1.0f / subPixF);
412 				Float y2 = Float(Y2) * (1.0f / subPixF);
413 
414 				Float D = *Pointer<Float>(data + OFFSET(DrawData, depthRange)) / (x1 * y2 - x2 * y1);
415 
416 				A = (y2 * z1 - y1 * z2) * D;
417 				B = (x1 * z2 - x2 * z1) * D;
418 			}
419 			else
420 			{
421 				A = 0.0f;
422 				B = 0.0f;
423 			}
424 
425 			C = z0 * *Pointer<Float>(data + OFFSET(DrawData, depthRange)) + *Pointer<Float>(data + OFFSET(DrawData, depthNear));
426 
427 			*Pointer<Float4>(primitive + OFFSET(Primitive, z.A), 16) = Float4(A);
428 			*Pointer<Float4>(primitive + OFFSET(Primitive, z.B), 16) = Float4(B);
429 			*Pointer<Float4>(primitive + OFFSET(Primitive, z.C), 16) = Float4(C);
430 
431 			Float bias = 0.0f;
432 
433 			if(state.applyConstantDepthBias)
434 			{
435 				Float r;  // Minimum resolvable difference
436 
437 				if(state.fixedPointDepthBuffer)
438 				{
439 					// TODO(b/139341727): Pre-multiply the constant depth bias factor by the minimum
440 					// resolvable difference.
441 
442 					// TODO(b/139341727): When there's a fixed-point depth buffer and no depth bias clamp,
443 					// the constant depth bias factor could be added to 'depthNear', eliminating the per-
444 					// polygon addition.
445 
446 					r = *Pointer<Float>(data + OFFSET(DrawData, minimumResolvableDepthDifference));
447 				}
448 				else  // Floating-point depth buffer
449 				{
450 					// "For floating-point depth buffers, there is no single minimum resolvable difference.
451 					//  In this case, the minimum resolvable difference for a given polygon is dependent on
452 					//  the maximum exponent, e, in the range of z values spanned by the primitive. If n is
453 					//  the number of bits in the floating-point mantissa, the minimum resolvable difference,
454 					//  r, for the given primitive is defined as r = 2^(e-n)."
455 
456 					Float Z0 = C;
457 					Float Z1 = z1 * *Pointer<Float>(data + OFFSET(DrawData, depthRange)) + *Pointer<Float>(data + OFFSET(DrawData, depthNear));
458 					Float Z2 = z2 * *Pointer<Float>(data + OFFSET(DrawData, depthRange)) + *Pointer<Float>(data + OFFSET(DrawData, depthNear));
459 
460 					Int e0 = As<Int>(Z0) & 0x7F800000;
461 					Int e1 = As<Int>(Z1) & 0x7F800000;
462 					Int e2 = As<Int>(Z2) & 0x7F800000;
463 
464 					Int e = Max(Max(e0, e1), e2);
465 
466 					r = As<Float>(e) * Float(1.0f / (1 << 23));
467 				}
468 
469 				bias = r * *Pointer<Float>(data + OFFSET(DrawData, constantDepthBias));
470 			}
471 
472 			if(state.applySlopeDepthBias)
473 			{
474 				Float m = Max(Abs(A), Abs(B));
475 
476 				bias += m * *Pointer<Float>(data + OFFSET(DrawData, slopeDepthBias));  // TODO(b/155302798): Optimize 0 += x;
477 			}
478 
479 			if(state.applyConstantDepthBias || state.applySlopeDepthBias)
480 			{
481 				if(state.applyDepthBiasClamp)
482 				{
483 					Float clamp = *Pointer<Float>(data + OFFSET(DrawData, depthBiasClamp));
484 
485 					bias = IfThenElse(clamp > 0.0f, Min(bias, clamp), Max(bias, clamp));
486 				}
487 
488 				*Pointer<Float4>(primitive + OFFSET(Primitive, zBias), 16) = Float4(bias);
489 			}
490 		}
491 
492 		int packedInterpolant = 0;
493 		for(int interfaceInterpolant = 0; interfaceInterpolant < MAX_INTERFACE_COMPONENTS; interfaceInterpolant++)
494 		{
495 			if(state.gradient[interfaceInterpolant].Type != SpirvShader::ATTRIBTYPE_UNUSED)
496 			{
497 				setupGradient(primitive, tri, w012, M, v0, v1, v2,
498 				              OFFSET(Vertex, v[interfaceInterpolant]),
499 				              OFFSET(Primitive, V[packedInterpolant]),
500 				              state.gradient[interfaceInterpolant].Flat,
501 				              !state.gradient[interfaceInterpolant].NoPerspective);
502 				packedInterpolant++;
503 			}
504 		}
505 
506 		for(unsigned int i = 0; i < state.numClipDistances; i++)
507 		{
508 			setupGradient(primitive, tri, w012, M, v0, v1, v2,
509 			              OFFSET(Vertex, clipDistance[i]),
510 			              OFFSET(Primitive, clipDistance[i]),
511 			              false, true);
512 		}
513 
514 		for(unsigned int i = 0; i < state.numCullDistances; i++)
515 		{
516 			setupGradient(primitive, tri, w012, M, v0, v1, v2,
517 			              OFFSET(Vertex, cullDistance[i]),
518 			              OFFSET(Primitive, cullDistance[i]),
519 			              false, true);
520 		}
521 
522 		Return(1);
523 	}
524 
525 	routine = function("SetupRoutine");
526 }
527 
setupGradient(Pointer<Byte> & primitive,Pointer<Byte> & triangle,Float4 & w012,Float4 (& m)[3],Pointer<Byte> & v0,Pointer<Byte> & v1,Pointer<Byte> & v2,int attribute,int planeEquation,bool flat,bool perspective)528 void SetupRoutine::setupGradient(Pointer<Byte> &primitive, Pointer<Byte> &triangle, Float4 &w012, Float4 (&m)[3], Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2, int attribute, int planeEquation, bool flat, bool perspective)
529 {
530 	if(!flat)
531 	{
532 		Float4 i;
533 		i.x = *Pointer<Float>(v0 + attribute);
534 		i.y = *Pointer<Float>(v1 + attribute);
535 		i.z = *Pointer<Float>(v2 + attribute);
536 		i.w = 0;
537 
538 		if(!perspective)
539 		{
540 			i *= w012;
541 		}
542 
543 		Float4 A = i.xxxx * m[0];
544 		Float4 B = i.yyyy * m[1];
545 		Float4 C = i.zzzz * m[2];
546 
547 		C = A + B + C;
548 
549 		A = C.xxxx;
550 		B = C.yyyy;
551 		C = C.zzzz;
552 
553 		*Pointer<Float4>(primitive + planeEquation + 0, 16) = A;
554 		*Pointer<Float4>(primitive + planeEquation + 16, 16) = B;
555 		*Pointer<Float4>(primitive + planeEquation + 32, 16) = C;
556 	}
557 	else
558 	{
559 		int leadingVertex = OFFSET(Triangle, v0);
560 		Float C = *Pointer<Float>(triangle + leadingVertex + attribute);
561 
562 		*Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0);
563 		*Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0);
564 		*Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C);
565 	}
566 }
567 
edge(Pointer<Byte> & primitive,Pointer<Byte> & data,const Int & Xa,const Int & Ya,const Int & Xb,const Int & Yb,Int & q)568 void SetupRoutine::edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &Xa, const Int &Ya, const Int &Xb, const Int &Yb, Int &q)
569 {
570 	If(Ya != Yb)
571 	{
572 		Bool swap = Yb < Ya;
573 
574 		Int X1 = IfThenElse(swap, Xb, Xa);
575 		Int X2 = IfThenElse(swap, Xa, Xb);
576 		Int Y1 = IfThenElse(swap, Yb, Ya);
577 		Int Y2 = IfThenElse(swap, Ya, Yb);
578 
579 		constexpr int subPixB = vk::SUBPIXEL_PRECISION_BITS;
580 		constexpr int subPixM = vk::SUBPIXEL_PRECISION_MASK;
581 
582 		Int y1 = Max((Y1 + subPixM) >> subPixB, *Pointer<Int>(data + OFFSET(DrawData, scissorY0)));
583 		Int y2 = Min((Y2 + subPixM) >> subPixB, *Pointer<Int>(data + OFFSET(DrawData, scissorY1)));
584 
585 		If(y1 < y2)
586 		{
587 			Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0));
588 			Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1));
589 
590 			Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->left);
591 			Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->right);
592 			Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge);
593 
594 			// Deltas
595 			Int DX12 = X2 - X1;
596 			Int DY12 = Y2 - Y1;
597 
598 			Int FDX12 = DX12 << subPixB;
599 			Int FDY12 = DY12 << subPixB;
600 
601 			Int X = DX12 * ((y1 << subPixB) - Y1) + (X1 & subPixM) * DY12;
602 			Int x = (X1 >> subPixB) + X / FDY12;  // Edge
603 			Int d = X % FDY12;                    // Error-term
604 			Int ceil = -d >> 31;                  // Ceiling division: remainder <= 0
605 			x -= ceil;
606 			d -= ceil & FDY12;
607 
608 			Int Q = FDX12 / FDY12;  // Edge-step
609 			Int R = FDX12 % FDY12;  // Error-step
610 			Int floor = R >> 31;    // Flooring division: remainder >= 0
611 			Q += floor;
612 			R += floor & FDY12;
613 
614 			Int D = FDY12;  // Error-overflow
615 			Int y = y1;
616 
617 			Do
618 			{
619 				*Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(Clamp(x, xMin, xMax));
620 
621 				x += Q;
622 				d += R;
623 
624 				Int overflow = -d >> 31;
625 
626 				d -= D & overflow;
627 				x -= overflow;
628 
629 				y++;
630 			}
631 			Until(y >= y2);
632 		}
633 	}
634 }
635 
conditionalRotate1(Bool condition,Pointer<Byte> & v0,Pointer<Byte> & v1,Pointer<Byte> & v2)636 void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
637 {
638 #if 0  // Rely on LLVM optimization
639 		If(condition)
640 		{
641 			Pointer<Byte> vX;
642 
643 			vX = v0;
644 			v0 = v1;
645 			v1 = v2;
646 			v2 = vX;
647 		}
648 #else
649 	Pointer<Byte> vX = v0;
650 	v0 = IfThenElse(condition, v1, v0);
651 	v1 = IfThenElse(condition, v2, v1);
652 	v2 = IfThenElse(condition, vX, v2);
653 #endif
654 }
655 
conditionalRotate2(Bool condition,Pointer<Byte> & v0,Pointer<Byte> & v1,Pointer<Byte> & v2)656 void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
657 {
658 #if 0  // Rely on LLVM optimization
659 		If(condition)
660 		{
661 			Pointer<Byte> vX;
662 
663 			vX = v2;
664 			v2 = v1;
665 			v1 = v0;
666 			v0 = vX;
667 		}
668 #else
669 	Pointer<Byte> vX = v2;
670 	v2 = IfThenElse(condition, v1, v2);
671 	v1 = IfThenElse(condition, v0, v1);
672 	v0 = IfThenElse(condition, vX, v0);
673 #endif
674 }
675 
getRoutine()676 SetupFunction::RoutineType SetupRoutine::getRoutine()
677 {
678 	return routine;
679 }
680 
681 }  // namespace sw
682