Simplify clipping of complex polygons

Polygons constructed for point and line rendering previously had clip
flags computed for each new vertex. This costs about as much as actually
performing full polygon clipping, so we can just do that immediately.

Note that for triangles we still take advantage of the clip flags that
cheaply get computed in parallel in the vertex routine, to skip polygon
clipping when fully inside the frustum.

Bug: b/207658159
Change-Id: I17e6c95bb7e9ffe601f5e4403cb0c43c62f7f941
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/67649
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/Device/Clipper.cpp b/src/Device/Clipper.cpp
index 5ab5534..54b27eb 100644
--- a/src/Device/Clipper.cpp
+++ b/src/Device/Clipper.cpp
@@ -261,18 +261,6 @@
 
 namespace sw {
 
-unsigned int Clipper::ComputeClipFlags(const float4 &v, bool depthClipEnable)
-{
-	int depthClipFlags = ((v.z > v.w) ? CLIP_FAR : 0) |
-	                     ((v.z < 0) ? CLIP_NEAR : 0);
-	return ((v.x > v.w) ? CLIP_RIGHT : 0) |
-	       ((v.y > v.w) ? CLIP_TOP : 0) |
-	       ((v.x < -v.w) ? CLIP_LEFT : 0) |
-	       ((v.y < -v.w) ? CLIP_BOTTOM : 0) |
-	       (depthClipEnable ? depthClipFlags : 0) |
-	       Clipper::CLIP_FINITE;  // FIXME: xyz finite
-}
-
 bool Clipper::Clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
 {
 	if(clipFlagsOr & CLIP_FRUSTUM)
diff --git a/src/Device/Clipper.hpp b/src/Device/Clipper.hpp
index a35a0b4..94e2c1b 100644
--- a/src/Device/Clipper.hpp
+++ b/src/Device/Clipper.hpp
@@ -34,12 +34,12 @@
 		CLIP_BOTTOM = 1 << 4,
 		CLIP_NEAR = 1 << 5,
 
-		CLIP_FRUSTUM = 0x003F,
+		CLIP_SIDES = CLIP_LEFT | CLIP_RIGHT | CLIP_BOTTOM | CLIP_TOP,
+		CLIP_FRUSTUM = CLIP_SIDES | CLIP_NEAR | CLIP_FAR,
 
 		CLIP_FINITE = 1 << 7,  // All position coordinates are finite
 	};
 
-	static unsigned int ComputeClipFlags(const float4 &v, bool depthClipEnable);
 	static bool Clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw);
 };
 
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 1017d0d..ce30ec5 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -355,7 +355,6 @@
 		data->constantDepthBias = pipelineState.getConstantDepthBias();
 		data->slopeDepthBias = pipelineState.getSlopeDepthBias();
 		data->depthBiasClamp = pipelineState.getDepthBiasClamp();
-		data->depthClipEnable = pipelineState.getDepthClipEnable();
 
 		const vk::Attachments attachments = pipeline->getAttachments();
 		if(attachments.depthBuffer)
@@ -849,12 +848,8 @@
 
 bool DrawCall::setupLine(vk::Device *device, Primitive &primitive, Triangle &triangle, const DrawCall &draw)
 {
-	const DrawData &data = *draw.data;
-
-	float lineWidth = data.lineWidth;
-
-	Vertex &v0 = triangle.v0;
-	Vertex &v1 = triangle.v1;
+	const Vertex &v0 = triangle.v0;
+	const Vertex &v1 = triangle.v1;
 
 	if((v0.cullMask | v1.cullMask) == 0)
 	{
@@ -869,6 +864,9 @@
 		return false;
 	}
 
+	const DrawData &data = *draw.data;
+	const float lineWidth = data.lineWidth;
+	const int clipFlags = draw.depthClipEnable ? Clipper::CLIP_FRUSTUM : Clipper::CLIP_SIDES;
 	constexpr float subPixF = vk::SUBPIXEL_PRECISION_FACTOR;
 
 	const float W = data.WxF * (1.0f / subPixF);
@@ -887,7 +885,6 @@
 		// Rectangle centered on the line segment
 
 		float4 P[4];
-		int C[4];
 
 		P[0] = P0;
 		P[1] = P1;
@@ -907,36 +904,24 @@
 
 		P[0].x += -dy0w;
 		P[0].y += +dx0h;
-		C[0] = Clipper::ComputeClipFlags(P[0], draw.depthClipEnable);
 
 		P[1].x += -dy1w;
 		P[1].y += +dx1h;
-		C[1] = Clipper::ComputeClipFlags(P[1], draw.depthClipEnable);
 
 		P[2].x += +dy1w;
 		P[2].y += -dx1h;
-		C[2] = Clipper::ComputeClipFlags(P[2], draw.depthClipEnable);
 
 		P[3].x += +dy0w;
 		P[3].y += -dx0h;
-		C[3] = Clipper::ComputeClipFlags(P[3], draw.depthClipEnable);
 
-		if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
+		Polygon polygon(P, 4);
+
+		if(!Clipper::Clip(polygon, clipFlags, draw))
 		{
-			Polygon polygon(P, 4);
-
-			int clipFlagsOr = C[0] | C[1] | C[2] | C[3];
-
-			if(clipFlagsOr != Clipper::CLIP_FINITE)
-			{
-				if(!Clipper::Clip(polygon, clipFlagsOr, draw))
-				{
-					return false;
-				}
-			}
-
-			return draw.setupRoutine(device, &primitive, &triangle, &polygon, &data);
+			return false;
 		}
+
+		return draw.setupRoutine(device, &primitive, &triangle, &polygon, &data);
 	}
 	else if(false)  // TODO(b/80135519): Deprecate
 	{
@@ -946,7 +931,6 @@
 		// The ideal algorithm requires half-open line rasterization (b/80135519).
 
 		float4 P[8];
-		int C[8];
 
 		P[0] = P0;
 		P[1] = P0;
@@ -964,90 +948,67 @@
 		float dy1 = lineWidth * 0.5f * P1.w / H;
 
 		P[0].x += -dx0;
-		C[0] = Clipper::ComputeClipFlags(P[0], draw.depthClipEnable);
-
 		P[1].y += +dy0;
-		C[1] = Clipper::ComputeClipFlags(P[1], draw.depthClipEnable);
-
 		P[2].x += +dx0;
-		C[2] = Clipper::ComputeClipFlags(P[2], draw.depthClipEnable);
-
 		P[3].y += -dy0;
-		C[3] = Clipper::ComputeClipFlags(P[3], draw.depthClipEnable);
-
 		P[4].x += -dx1;
-		C[4] = Clipper::ComputeClipFlags(P[4], draw.depthClipEnable);
-
 		P[5].y += +dy1;
-		C[5] = Clipper::ComputeClipFlags(P[5], draw.depthClipEnable);
-
 		P[6].x += +dx1;
-		C[6] = Clipper::ComputeClipFlags(P[6], draw.depthClipEnable);
-
 		P[7].y += -dy1;
-		C[7] = Clipper::ComputeClipFlags(P[7], draw.depthClipEnable);
 
-		if((C[0] & C[1] & C[2] & C[3] & C[4] & C[5] & C[6] & C[7]) == Clipper::CLIP_FINITE)
+		float4 L[6];
+
+		if(dx > -dy)
 		{
-			float4 L[6];
-
-			if(dx > -dy)
+			if(dx > dy)  // Right
 			{
-				if(dx > dy)  // Right
-				{
-					L[0] = P[0];
-					L[1] = P[1];
-					L[2] = P[5];
-					L[3] = P[6];
-					L[4] = P[7];
-					L[5] = P[3];
-				}
-				else  // Down
-				{
-					L[0] = P[0];
-					L[1] = P[4];
-					L[2] = P[5];
-					L[3] = P[6];
-					L[4] = P[2];
-					L[5] = P[3];
-				}
+				L[0] = P[0];
+				L[1] = P[1];
+				L[2] = P[5];
+				L[3] = P[6];
+				L[4] = P[7];
+				L[5] = P[3];
 			}
-			else
+			else  // Down
 			{
-				if(dx > dy)  // Up
-				{
-					L[0] = P[0];
-					L[1] = P[1];
-					L[2] = P[2];
-					L[3] = P[6];
-					L[4] = P[7];
-					L[5] = P[4];
-				}
-				else  // Left
-				{
-					L[0] = P[1];
-					L[1] = P[2];
-					L[2] = P[3];
-					L[3] = P[7];
-					L[4] = P[4];
-					L[5] = P[5];
-				}
+				L[0] = P[0];
+				L[1] = P[4];
+				L[2] = P[5];
+				L[3] = P[6];
+				L[4] = P[2];
+				L[5] = P[3];
 			}
-
-			Polygon polygon(L, 6);
-
-			int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | C[4] | C[5] | C[6] | C[7];
-
-			if(clipFlagsOr != Clipper::CLIP_FINITE)
-			{
-				if(!Clipper::Clip(polygon, clipFlagsOr, draw))
-				{
-					return false;
-				}
-			}
-
-			return draw.setupRoutine(device, &primitive, &triangle, &polygon, &data);
 		}
+		else
+		{
+			if(dx > dy)  // Up
+			{
+				L[0] = P[0];
+				L[1] = P[1];
+				L[2] = P[2];
+				L[3] = P[6];
+				L[4] = P[7];
+				L[5] = P[4];
+			}
+			else  // Left
+			{
+				L[0] = P[1];
+				L[1] = P[2];
+				L[2] = P[3];
+				L[3] = P[7];
+				L[4] = P[4];
+				L[5] = P[5];
+			}
+		}
+
+		Polygon polygon(L, 6);
+
+		if(!Clipper::Clip(polygon, clipFlags, draw))
+		{
+			return false;
+		}
+
+		return draw.setupRoutine(device, &primitive, &triangle, &polygon, &data);
 	}
 	else
 	{
@@ -1118,27 +1079,14 @@
 			}
 		}
 
-		int C0 = Clipper::ComputeClipFlags(L[0], draw.depthClipEnable);
-		int C1 = Clipper::ComputeClipFlags(L[1], draw.depthClipEnable);
-		int C2 = Clipper::ComputeClipFlags(L[2], draw.depthClipEnable);
-		int C3 = Clipper::ComputeClipFlags(L[3], draw.depthClipEnable);
+		Polygon polygon(L, 4);
 
-		if((C0 & C1 & C2 & C3) == Clipper::CLIP_FINITE)
+		if(!Clipper::Clip(polygon, clipFlags, draw))
 		{
-			Polygon polygon(L, 4);
-
-			int clipFlagsOr = C0 | C1 | C2 | C3;
-
-			if(clipFlagsOr != Clipper::CLIP_FINITE)
-			{
-				if(!Clipper::Clip(polygon, clipFlagsOr, draw))
-				{
-					return false;
-				}
-			}
-
-			return draw.setupRoutine(device, &primitive, &triangle, &polygon, &data);
+			return false;
 		}
+
+		return draw.setupRoutine(device, &primitive, &triangle, &polygon, &data);
 	}
 
 	return false;
@@ -1146,66 +1094,48 @@
 
 bool DrawCall::setupPoint(vk::Device *device, Primitive &primitive, Triangle &triangle, const DrawCall &draw)
 {
-	const DrawData &data = *draw.data;
-
-	Vertex &v = triangle.v0;
+	const Vertex &v = triangle.v0;
 
 	if(v.cullMask == 0)
 	{
 		return false;
 	}
 
-	float pSize = v.pointSize;
+	const DrawData &data = *draw.data;
+	const int clipFlags = draw.depthClipEnable ? Clipper::CLIP_FRUSTUM : Clipper::CLIP_SIDES;
 
-	pSize = clamp(pSize, 1.0f, static_cast<float>(vk::MAX_POINT_SIZE));
+	const float pSize = clamp(v.pointSize, 1.0f, static_cast<float>(vk::MAX_POINT_SIZE));
+	const float X = pSize * v.position.w * data.halfPixelX;
+	const float Y = pSize * v.position.w * data.halfPixelY;
 
 	float4 P[4];
-	int C[4];
 
 	P[0] = v.position;
-	P[1] = v.position;
-	P[2] = v.position;
-	P[3] = v.position;
-
-	const float X = pSize * P[0].w * data.halfPixelX;
-	const float Y = pSize * P[0].w * data.halfPixelY;
-
 	P[0].x -= X;
 	P[0].y += Y;
-	C[0] = Clipper::ComputeClipFlags(P[0], draw.depthClipEnable);
 
+	P[1] = v.position;
 	P[1].x += X;
 	P[1].y += Y;
-	C[1] = Clipper::ComputeClipFlags(P[1], draw.depthClipEnable);
 
+	P[2] = v.position;
 	P[2].x += X;
 	P[2].y -= Y;
-	C[2] = Clipper::ComputeClipFlags(P[2], draw.depthClipEnable);
 
+	P[3] = v.position;
 	P[3].x -= X;
 	P[3].y -= Y;
-	C[3] = Clipper::ComputeClipFlags(P[3], draw.depthClipEnable);
 
 	Polygon polygon(P, 4);
 
-	if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
+	if(!Clipper::Clip(polygon, clipFlags, draw))
 	{
-		int clipFlagsOr = C[0] | C[1] | C[2] | C[3];
-
-		if(clipFlagsOr != Clipper::CLIP_FINITE)
-		{
-			if(!Clipper::Clip(polygon, clipFlagsOr, draw))
-			{
-				return false;
-			}
-		}
-
-		primitive.pointSizeInv = 1.0f / pSize;
-
-		return draw.setupRoutine(device, &primitive, &triangle, &polygon, &data);
+		return false;
 	}
 
-	return false;
+	primitive.pointSizeInv = 1.0f / pSize;
+
+	return draw.setupRoutine(device, &primitive, &triangle, &polygon, &data);
 }
 
 void Renderer::addQuery(vk::Query *query)
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index 1c155e5..8263522 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -87,7 +87,6 @@
 	float constantDepthBias;
 	float slopeDepthBias;
 	float depthBiasClamp;
-	bool depthClipEnable;
 
 	unsigned int *colorBuffer[MAX_COLOR_BUFFERS];
 	int colorPitchB[MAX_COLOR_BUFFERS];