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