xref: /aosp_15_r20/external/swiftshader/src/Device/QuadRasterizer.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 "QuadRasterizer.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "Primitive.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "Renderer.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "Pipeline/Constants.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "System/Debug.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "System/Math.hpp"
22*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkDevice.hpp"
23*03ce13f7SAndroid Build Coastguard Worker 
24*03ce13f7SAndroid Build Coastguard Worker namespace sw {
25*03ce13f7SAndroid Build Coastguard Worker 
QuadRasterizer(const PixelProcessor::State & state,const SpirvShader * spirvShader)26*03ce13f7SAndroid Build Coastguard Worker QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, const SpirvShader *spirvShader)
27*03ce13f7SAndroid Build Coastguard Worker     : state(state)
28*03ce13f7SAndroid Build Coastguard Worker     , spirvShader{ spirvShader }
29*03ce13f7SAndroid Build Coastguard Worker {
30*03ce13f7SAndroid Build Coastguard Worker }
31*03ce13f7SAndroid Build Coastguard Worker 
~QuadRasterizer()32*03ce13f7SAndroid Build Coastguard Worker QuadRasterizer::~QuadRasterizer()
33*03ce13f7SAndroid Build Coastguard Worker {
34*03ce13f7SAndroid Build Coastguard Worker }
35*03ce13f7SAndroid Build Coastguard Worker 
generate()36*03ce13f7SAndroid Build Coastguard Worker void QuadRasterizer::generate()
37*03ce13f7SAndroid Build Coastguard Worker {
38*03ce13f7SAndroid Build Coastguard Worker 	constants = device + OFFSET(vk::Device, constants);
39*03ce13f7SAndroid Build Coastguard Worker 	occlusion = 0;
40*03ce13f7SAndroid Build Coastguard Worker 
41*03ce13f7SAndroid Build Coastguard Worker 	Do
42*03ce13f7SAndroid Build Coastguard Worker 	{
43*03ce13f7SAndroid Build Coastguard Worker 		Int yMin = *Pointer<Int>(primitive + OFFSET(Primitive, yMin));
44*03ce13f7SAndroid Build Coastguard Worker 		Int yMax = *Pointer<Int>(primitive + OFFSET(Primitive, yMax));
45*03ce13f7SAndroid Build Coastguard Worker 
46*03ce13f7SAndroid Build Coastguard Worker 		Int cluster2 = cluster + cluster;
47*03ce13f7SAndroid Build Coastguard Worker 		yMin += clusterCount * 2 - 2 - cluster2;
48*03ce13f7SAndroid Build Coastguard Worker 		yMin &= -clusterCount * 2;
49*03ce13f7SAndroid Build Coastguard Worker 		yMin += cluster2;
50*03ce13f7SAndroid Build Coastguard Worker 
51*03ce13f7SAndroid Build Coastguard Worker 		If(yMin < yMax)
52*03ce13f7SAndroid Build Coastguard Worker 		{
53*03ce13f7SAndroid Build Coastguard Worker 			rasterize(yMin, yMax);
54*03ce13f7SAndroid Build Coastguard Worker 		}
55*03ce13f7SAndroid Build Coastguard Worker 
56*03ce13f7SAndroid Build Coastguard Worker 		primitive += sizeof(Primitive) * state.multiSampleCount;
57*03ce13f7SAndroid Build Coastguard Worker 		count--;
58*03ce13f7SAndroid Build Coastguard Worker 	}
59*03ce13f7SAndroid Build Coastguard Worker 	Until(count == 0);
60*03ce13f7SAndroid Build Coastguard Worker 
61*03ce13f7SAndroid Build Coastguard Worker 	if(state.occlusionEnabled)
62*03ce13f7SAndroid Build Coastguard Worker 	{
63*03ce13f7SAndroid Build Coastguard Worker 		UInt clusterOcclusion = *Pointer<UInt>(data + OFFSET(DrawData, occlusion) + 4 * cluster);
64*03ce13f7SAndroid Build Coastguard Worker 		clusterOcclusion += occlusion;
65*03ce13f7SAndroid Build Coastguard Worker 		*Pointer<UInt>(data + OFFSET(DrawData, occlusion) + 4 * cluster) = clusterOcclusion;
66*03ce13f7SAndroid Build Coastguard Worker 	}
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker 	Return();
69*03ce13f7SAndroid Build Coastguard Worker }
70*03ce13f7SAndroid Build Coastguard Worker 
rasterize(Int & yMin,Int & yMax)71*03ce13f7SAndroid Build Coastguard Worker void QuadRasterizer::rasterize(Int &yMin, Int &yMax)
72*03ce13f7SAndroid Build Coastguard Worker {
73*03ce13f7SAndroid Build Coastguard Worker 	Pointer<Byte> cBuffer[MAX_COLOR_BUFFERS];
74*03ce13f7SAndroid Build Coastguard Worker 	Pointer<Byte> zBuffer;
75*03ce13f7SAndroid Build Coastguard Worker 	Pointer<Byte> sBuffer;
76*03ce13f7SAndroid Build Coastguard Worker 
77*03ce13f7SAndroid Build Coastguard Worker 	Int clusterCountLog2 = 31 - Ctlz(UInt(clusterCount), false);
78*03ce13f7SAndroid Build Coastguard Worker 
79*03ce13f7SAndroid Build Coastguard Worker 	for(int index = 0; index < MAX_COLOR_BUFFERS; index++)
80*03ce13f7SAndroid Build Coastguard Worker 	{
81*03ce13f7SAndroid Build Coastguard Worker 		if(state.colorWriteActive(index))
82*03ce13f7SAndroid Build Coastguard Worker 		{
83*03ce13f7SAndroid Build Coastguard Worker 			cBuffer[index] = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, colorBuffer[index])) + yMin * *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
84*03ce13f7SAndroid Build Coastguard Worker 		}
85*03ce13f7SAndroid Build Coastguard Worker 	}
86*03ce13f7SAndroid Build Coastguard Worker 
87*03ce13f7SAndroid Build Coastguard Worker 	if(state.depthTestActive || state.depthBoundsTestActive)
88*03ce13f7SAndroid Build Coastguard Worker 	{
89*03ce13f7SAndroid Build Coastguard Worker 		zBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, depthBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData, depthPitchB));
90*03ce13f7SAndroid Build Coastguard Worker 	}
91*03ce13f7SAndroid Build Coastguard Worker 
92*03ce13f7SAndroid Build Coastguard Worker 	if(state.stencilActive)
93*03ce13f7SAndroid Build Coastguard Worker 	{
94*03ce13f7SAndroid Build Coastguard Worker 		sBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, stencilBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData, stencilPitchB));
95*03ce13f7SAndroid Build Coastguard Worker 	}
96*03ce13f7SAndroid Build Coastguard Worker 
97*03ce13f7SAndroid Build Coastguard Worker 	Int y = yMin;
98*03ce13f7SAndroid Build Coastguard Worker 
99*03ce13f7SAndroid Build Coastguard Worker 	Do
100*03ce13f7SAndroid Build Coastguard Worker 	{
101*03ce13f7SAndroid Build Coastguard Worker 		Int x0a = Int(*Pointer<Short>(primitive + OFFSET(Primitive, outline->left) + (y + 0) * sizeof(Primitive::Span)));
102*03ce13f7SAndroid Build Coastguard Worker 		Int x0b = Int(*Pointer<Short>(primitive + OFFSET(Primitive, outline->left) + (y + 1) * sizeof(Primitive::Span)));
103*03ce13f7SAndroid Build Coastguard Worker 		Int x0 = Min(x0a, x0b);
104*03ce13f7SAndroid Build Coastguard Worker 
105*03ce13f7SAndroid Build Coastguard Worker 		for(unsigned int q = 1; q < state.multiSampleCount; q++)
106*03ce13f7SAndroid Build Coastguard Worker 		{
107*03ce13f7SAndroid Build Coastguard Worker 			x0a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->left) + (y + 0) * sizeof(Primitive::Span)));
108*03ce13f7SAndroid Build Coastguard Worker 			x0b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->left) + (y + 1) * sizeof(Primitive::Span)));
109*03ce13f7SAndroid Build Coastguard Worker 			x0 = Min(x0, Min(x0a, x0b));
110*03ce13f7SAndroid Build Coastguard Worker 		}
111*03ce13f7SAndroid Build Coastguard Worker 
112*03ce13f7SAndroid Build Coastguard Worker 		x0 &= 0xFFFFFFFE;
113*03ce13f7SAndroid Build Coastguard Worker 
114*03ce13f7SAndroid Build Coastguard Worker 		Int x1a = Int(*Pointer<Short>(primitive + OFFSET(Primitive, outline->right) + (y + 0) * sizeof(Primitive::Span)));
115*03ce13f7SAndroid Build Coastguard Worker 		Int x1b = Int(*Pointer<Short>(primitive + OFFSET(Primitive, outline->right) + (y + 1) * sizeof(Primitive::Span)));
116*03ce13f7SAndroid Build Coastguard Worker 		Int x1 = Max(x1a, x1b);
117*03ce13f7SAndroid Build Coastguard Worker 
118*03ce13f7SAndroid Build Coastguard Worker 		for(unsigned int q = 1; q < state.multiSampleCount; q++)
119*03ce13f7SAndroid Build Coastguard Worker 		{
120*03ce13f7SAndroid Build Coastguard Worker 			x1a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->right) + (y + 0) * sizeof(Primitive::Span)));
121*03ce13f7SAndroid Build Coastguard Worker 			x1b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->right) + (y + 1) * sizeof(Primitive::Span)));
122*03ce13f7SAndroid Build Coastguard Worker 			x1 = Max(x1, Max(x1a, x1b));
123*03ce13f7SAndroid Build Coastguard Worker 		}
124*03ce13f7SAndroid Build Coastguard Worker 
125*03ce13f7SAndroid Build Coastguard Worker 		// Compute the y coordinate of each fragment in the SIMD group.
126*03ce13f7SAndroid Build Coastguard Worker 		const auto yMorton = SIMD::Float([](int i) { return float(compactEvenBits(i >> 1)); });  // 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, ...
127*03ce13f7SAndroid Build Coastguard Worker 		yFragment = SIMD::Float(Float(y)) + yMorton - SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, y0)));
128*03ce13f7SAndroid Build Coastguard Worker 
129*03ce13f7SAndroid Build Coastguard Worker 		if(interpolateZ())
130*03ce13f7SAndroid Build Coastguard Worker 		{
131*03ce13f7SAndroid Build Coastguard Worker 			for(unsigned int q = 0; q < state.multiSampleCount; q++)
132*03ce13f7SAndroid Build Coastguard Worker 			{
133*03ce13f7SAndroid Build Coastguard Worker 				SIMD::Float y = yFragment;
134*03ce13f7SAndroid Build Coastguard Worker 
135*03ce13f7SAndroid Build Coastguard Worker 				if(state.enableMultiSampling)
136*03ce13f7SAndroid Build Coastguard Worker 				{
137*03ce13f7SAndroid Build Coastguard Worker 					y += SIMD::Float(*Pointer<Float>(constants + OFFSET(Constants, SampleLocationsY) + q * sizeof(float)));
138*03ce13f7SAndroid Build Coastguard Worker 				}
139*03ce13f7SAndroid Build Coastguard Worker 
140*03ce13f7SAndroid Build Coastguard Worker 				Dz[q] = SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, z.C))) + y * SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, z.B)));
141*03ce13f7SAndroid Build Coastguard Worker 			}
142*03ce13f7SAndroid Build Coastguard Worker 		}
143*03ce13f7SAndroid Build Coastguard Worker 
144*03ce13f7SAndroid Build Coastguard Worker 		If(x0 < x1)
145*03ce13f7SAndroid Build Coastguard Worker 		{
146*03ce13f7SAndroid Build Coastguard Worker 			if(interpolateW())
147*03ce13f7SAndroid Build Coastguard Worker 			{
148*03ce13f7SAndroid Build Coastguard Worker 				Dw = SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, w.C))) + yFragment * SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, w.B)));
149*03ce13f7SAndroid Build Coastguard Worker 			}
150*03ce13f7SAndroid Build Coastguard Worker 
151*03ce13f7SAndroid Build Coastguard Worker 			if(spirvShader)
152*03ce13f7SAndroid Build Coastguard Worker 			{
153*03ce13f7SAndroid Build Coastguard Worker 				int packedInterpolant = 0;
154*03ce13f7SAndroid Build Coastguard Worker 				for(int interfaceInterpolant = 0; interfaceInterpolant < MAX_INTERFACE_COMPONENTS; interfaceInterpolant++)
155*03ce13f7SAndroid Build Coastguard Worker 				{
156*03ce13f7SAndroid Build Coastguard Worker 					if(spirvShader->inputs[interfaceInterpolant].Type != SpirvShader::ATTRIBTYPE_UNUSED)
157*03ce13f7SAndroid Build Coastguard Worker 					{
158*03ce13f7SAndroid Build Coastguard Worker 						Dv[interfaceInterpolant] = *Pointer<Float>(primitive + OFFSET(Primitive, V[packedInterpolant].C));
159*03ce13f7SAndroid Build Coastguard Worker 						if(!spirvShader->inputs[interfaceInterpolant].Flat)
160*03ce13f7SAndroid Build Coastguard Worker 						{
161*03ce13f7SAndroid Build Coastguard Worker 							Dv[interfaceInterpolant] +=
162*03ce13f7SAndroid Build Coastguard Worker 							    yFragment * SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, V[packedInterpolant].B)));
163*03ce13f7SAndroid Build Coastguard Worker 						}
164*03ce13f7SAndroid Build Coastguard Worker 						packedInterpolant++;
165*03ce13f7SAndroid Build Coastguard Worker 					}
166*03ce13f7SAndroid Build Coastguard Worker 				}
167*03ce13f7SAndroid Build Coastguard Worker 
168*03ce13f7SAndroid Build Coastguard Worker 				for(unsigned int i = 0; i < state.numClipDistances; i++)
169*03ce13f7SAndroid Build Coastguard Worker 				{
170*03ce13f7SAndroid Build Coastguard Worker 					DclipDistance[i] = SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, clipDistance[i].C))) +
171*03ce13f7SAndroid Build Coastguard Worker 					                   yFragment * SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, clipDistance[i].B)));
172*03ce13f7SAndroid Build Coastguard Worker 				}
173*03ce13f7SAndroid Build Coastguard Worker 
174*03ce13f7SAndroid Build Coastguard Worker 				for(unsigned int i = 0; i < state.numCullDistances; i++)
175*03ce13f7SAndroid Build Coastguard Worker 				{
176*03ce13f7SAndroid Build Coastguard Worker 					DcullDistance[i] = SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, cullDistance[i].C))) +
177*03ce13f7SAndroid Build Coastguard Worker 					                   yFragment * SIMD::Float(*Pointer<Float>(primitive + OFFSET(Primitive, cullDistance[i].B)));
178*03ce13f7SAndroid Build Coastguard Worker 				}
179*03ce13f7SAndroid Build Coastguard Worker 			}
180*03ce13f7SAndroid Build Coastguard Worker 
181*03ce13f7SAndroid Build Coastguard Worker 			Short4 xLeft[4];
182*03ce13f7SAndroid Build Coastguard Worker 			Short4 xRight[4];
183*03ce13f7SAndroid Build Coastguard Worker 
184*03ce13f7SAndroid Build Coastguard Worker 			for(unsigned int q = 0; q < state.multiSampleCount; q++)
185*03ce13f7SAndroid Build Coastguard Worker 			{
186*03ce13f7SAndroid Build Coastguard Worker 				xLeft[q] = *Pointer<Short4>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline) + y * sizeof(Primitive::Span));
187*03ce13f7SAndroid Build Coastguard Worker 				xRight[q] = xLeft[q];
188*03ce13f7SAndroid Build Coastguard Worker 
189*03ce13f7SAndroid Build Coastguard Worker 				xLeft[q] = Swizzle(xLeft[q], 0x0022) - Short4(1, 2, 1, 2);
190*03ce13f7SAndroid Build Coastguard Worker 				xRight[q] = Swizzle(xRight[q], 0x1133) - Short4(0, 1, 0, 1);
191*03ce13f7SAndroid Build Coastguard Worker 			}
192*03ce13f7SAndroid Build Coastguard Worker 
193*03ce13f7SAndroid Build Coastguard Worker 			For(Int x = x0, x < x1, x += 2)
194*03ce13f7SAndroid Build Coastguard Worker 			{
195*03ce13f7SAndroid Build Coastguard Worker 				Short4 xxxx = Short4(x);
196*03ce13f7SAndroid Build Coastguard Worker 				Int cMask[4];
197*03ce13f7SAndroid Build Coastguard Worker 
198*03ce13f7SAndroid Build Coastguard Worker 				for(unsigned int q = 0; q < state.multiSampleCount; q++)
199*03ce13f7SAndroid Build Coastguard Worker 				{
200*03ce13f7SAndroid Build Coastguard Worker 					if(state.multiSampleMask & (1 << q))
201*03ce13f7SAndroid Build Coastguard Worker 					{
202*03ce13f7SAndroid Build Coastguard Worker 						unsigned int i = state.enableMultiSampling ? q : 0;
203*03ce13f7SAndroid Build Coastguard Worker 						Short4 mask = CmpGT(xxxx, xLeft[i]) & CmpGT(xRight[i], xxxx);
204*03ce13f7SAndroid Build Coastguard Worker 						cMask[q] = SignMask(PackSigned(mask, mask)) & 0x0000000F;
205*03ce13f7SAndroid Build Coastguard Worker 					}
206*03ce13f7SAndroid Build Coastguard Worker 				}
207*03ce13f7SAndroid Build Coastguard Worker 
208*03ce13f7SAndroid Build Coastguard Worker 				quad(cBuffer, zBuffer, sBuffer, cMask, x, y);
209*03ce13f7SAndroid Build Coastguard Worker 			}
210*03ce13f7SAndroid Build Coastguard Worker 		}
211*03ce13f7SAndroid Build Coastguard Worker 
212*03ce13f7SAndroid Build Coastguard Worker 		for(int index = 0; index < MAX_COLOR_BUFFERS; index++)
213*03ce13f7SAndroid Build Coastguard Worker 		{
214*03ce13f7SAndroid Build Coastguard Worker 			if(state.colorWriteActive(index))
215*03ce13f7SAndroid Build Coastguard Worker 			{
216*03ce13f7SAndroid Build Coastguard Worker 				cBuffer[index] += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])) << (1 + clusterCountLog2);  // FIXME: Precompute
217*03ce13f7SAndroid Build Coastguard Worker 			}
218*03ce13f7SAndroid Build Coastguard Worker 		}
219*03ce13f7SAndroid Build Coastguard Worker 
220*03ce13f7SAndroid Build Coastguard Worker 		if(state.depthTestActive || state.depthBoundsTestActive)
221*03ce13f7SAndroid Build Coastguard Worker 		{
222*03ce13f7SAndroid Build Coastguard Worker 			zBuffer += *Pointer<Int>(data + OFFSET(DrawData, depthPitchB)) << (1 + clusterCountLog2);  // FIXME: Precompute
223*03ce13f7SAndroid Build Coastguard Worker 		}
224*03ce13f7SAndroid Build Coastguard Worker 
225*03ce13f7SAndroid Build Coastguard Worker 		if(state.stencilActive)
226*03ce13f7SAndroid Build Coastguard Worker 		{
227*03ce13f7SAndroid Build Coastguard Worker 			sBuffer += *Pointer<Int>(data + OFFSET(DrawData, stencilPitchB)) << (1 + clusterCountLog2);  // FIXME: Precompute
228*03ce13f7SAndroid Build Coastguard Worker 		}
229*03ce13f7SAndroid Build Coastguard Worker 
230*03ce13f7SAndroid Build Coastguard Worker 		y += 2 * clusterCount;
231*03ce13f7SAndroid Build Coastguard Worker 	}
232*03ce13f7SAndroid Build Coastguard Worker 	Until(y >= yMax);
233*03ce13f7SAndroid Build Coastguard Worker }
234*03ce13f7SAndroid Build Coastguard Worker 
interpolate(SIMD::Float & x,SIMD::Float & D,SIMD::Float & rhw,Pointer<Byte> planeEquation,bool flat,bool perspective)235*03ce13f7SAndroid Build Coastguard Worker SIMD::Float QuadRasterizer::interpolate(SIMD::Float &x, SIMD::Float &D, SIMD::Float &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective)
236*03ce13f7SAndroid Build Coastguard Worker {
237*03ce13f7SAndroid Build Coastguard Worker 	if(flat)
238*03ce13f7SAndroid Build Coastguard Worker 	{
239*03ce13f7SAndroid Build Coastguard Worker 		return D;
240*03ce13f7SAndroid Build Coastguard Worker 	}
241*03ce13f7SAndroid Build Coastguard Worker 
242*03ce13f7SAndroid Build Coastguard Worker 	SIMD::Float interpolant = mulAdd(x, SIMD::Float(*Pointer<Float>(planeEquation + OFFSET(PlaneEquation, A))), D);
243*03ce13f7SAndroid Build Coastguard Worker 
244*03ce13f7SAndroid Build Coastguard Worker 	if(perspective)
245*03ce13f7SAndroid Build Coastguard Worker 	{
246*03ce13f7SAndroid Build Coastguard Worker 		interpolant *= rhw;
247*03ce13f7SAndroid Build Coastguard Worker 	}
248*03ce13f7SAndroid Build Coastguard Worker 
249*03ce13f7SAndroid Build Coastguard Worker 	return interpolant;
250*03ce13f7SAndroid Build Coastguard Worker }
251*03ce13f7SAndroid Build Coastguard Worker 
interpolateZ() const252*03ce13f7SAndroid Build Coastguard Worker bool QuadRasterizer::interpolateZ() const
253*03ce13f7SAndroid Build Coastguard Worker {
254*03ce13f7SAndroid Build Coastguard Worker 	return state.depthTestActive || (spirvShader && spirvShader->hasBuiltinInput(spv::BuiltInFragCoord));
255*03ce13f7SAndroid Build Coastguard Worker }
256*03ce13f7SAndroid Build Coastguard Worker 
interpolateW() const257*03ce13f7SAndroid Build Coastguard Worker bool QuadRasterizer::interpolateW() const
258*03ce13f7SAndroid Build Coastguard Worker {
259*03ce13f7SAndroid Build Coastguard Worker 	// Note: could optimize cases where there is a fragment shader but it has no
260*03ce13f7SAndroid Build Coastguard Worker 	// perspective-correct inputs, but that's vanishingly rare.
261*03ce13f7SAndroid Build Coastguard Worker 	return spirvShader != nullptr;
262*03ce13f7SAndroid Build Coastguard Worker }
263*03ce13f7SAndroid Build Coastguard Worker 
264*03ce13f7SAndroid Build Coastguard Worker }  // namespace sw
265