Fix crash in vertex shader when position is not declared

It is legal for a shader to not declare BuiltInPosition.
This cl adds logic to use 0 for all position components
when the position builtin is not present and then keeps
executing the rest of the shader normally.

Bug: b/176161380
Change-Id: I1b4637b813d3d30958e2db655d299603d625c20a
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51808
Commit-Queue: Alexis Hétu <sugoi@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/VertexRoutine.cpp b/src/Pipeline/VertexRoutine.cpp
index cc095b7..2d5167d 100644
--- a/src/Pipeline/VertexRoutine.cpp
+++ b/src/Pipeline/VertexRoutine.cpp
@@ -114,35 +114,37 @@
 void VertexRoutine::computeClipFlags()
 {
 	auto it = spirvShader->outputBuiltins.find(spv::BuiltInPosition);
-	assert(it != spirvShader->outputBuiltins.end());
-	assert(it->second.SizeInComponents == 4);
-	auto &pos = routine.getVariable(it->second.Id);
-	auto posX = pos[it->second.FirstComponent + 0];
-	auto posY = pos[it->second.FirstComponent + 1];
-	auto posZ = pos[it->second.FirstComponent + 2];
-	auto posW = pos[it->second.FirstComponent + 3];
+	if(it != spirvShader->outputBuiltins.end())
+	{
+		assert(it->second.SizeInComponents == 4);
+		auto &pos = routine.getVariable(it->second.Id);
+		auto posX = pos[it->second.FirstComponent + 0];
+		auto posY = pos[it->second.FirstComponent + 1];
+		auto posZ = pos[it->second.FirstComponent + 2];
+		auto posW = pos[it->second.FirstComponent + 3];
 
-	Int4 maxX = CmpLT(posW, posX);
-	Int4 maxY = CmpLT(posW, posY);
-	Int4 maxZ = CmpLT(posW, posZ);
-	Int4 minX = CmpNLE(-posW, posX);
-	Int4 minY = CmpNLE(-posW, posY);
-	Int4 minZ = CmpNLE(Float4(0.0f), posZ);
+		Int4 maxX = CmpLT(posW, posX);
+		Int4 maxY = CmpLT(posW, posY);
+		Int4 maxZ = CmpLT(posW, posZ);
+		Int4 minX = CmpNLE(-posW, posX);
+		Int4 minY = CmpNLE(-posW, posY);
+		Int4 minZ = CmpNLE(Float4(0.0f), posZ);
 
-	clipFlags = Pointer<Int>(constants + OFFSET(Constants, maxX))[SignMask(maxX)];
-	clipFlags |= Pointer<Int>(constants + OFFSET(Constants, maxY))[SignMask(maxY)];
-	clipFlags |= Pointer<Int>(constants + OFFSET(Constants, maxZ))[SignMask(maxZ)];
-	clipFlags |= Pointer<Int>(constants + OFFSET(Constants, minX))[SignMask(minX)];
-	clipFlags |= Pointer<Int>(constants + OFFSET(Constants, minY))[SignMask(minY)];
-	clipFlags |= Pointer<Int>(constants + OFFSET(Constants, minZ))[SignMask(minZ)];
+		clipFlags = Pointer<Int>(constants + OFFSET(Constants, maxX))[SignMask(maxX)];
+		clipFlags |= Pointer<Int>(constants + OFFSET(Constants, maxY))[SignMask(maxY)];
+		clipFlags |= Pointer<Int>(constants + OFFSET(Constants, maxZ))[SignMask(maxZ)];
+		clipFlags |= Pointer<Int>(constants + OFFSET(Constants, minX))[SignMask(minX)];
+		clipFlags |= Pointer<Int>(constants + OFFSET(Constants, minY))[SignMask(minY)];
+		clipFlags |= Pointer<Int>(constants + OFFSET(Constants, minZ))[SignMask(minZ)];
 
-	Float4 maxPos = As<Float4>(Int4(0x7F7FFFFF));
-	Int4 finiteX = CmpLE(Abs(posX), maxPos);
-	Int4 finiteY = CmpLE(Abs(posY), maxPos);
-	Int4 finiteZ = CmpLE(Abs(posZ), maxPos);
+		Float4 maxPos = As<Float4>(Int4(0x7F7FFFFF));
+		Int4 finiteX = CmpLE(Abs(posX), maxPos);
+		Int4 finiteY = CmpLE(Abs(posY), maxPos);
+		Int4 finiteZ = CmpLE(Abs(posZ), maxPos);
 
-	Int4 finiteXYZ = finiteX & finiteY & finiteZ;
-	clipFlags |= Pointer<Int>(constants + OFFSET(Constants, fini))[SignMask(finiteXYZ)];
+		Int4 finiteXYZ = finiteX & finiteY & finiteZ;
+		clipFlags |= Pointer<Int>(constants + OFFSET(Constants, fini))[SignMask(finiteXYZ)];
+	}
 }
 
 void VertexRoutine::computeCullMask()
@@ -531,32 +533,46 @@
 	tagCache[cacheIndex0] = index0;
 
 	auto it = spirvShader->outputBuiltins.find(spv::BuiltInPosition);
-	assert(it != spirvShader->outputBuiltins.end());
-	assert(it->second.SizeInComponents == 4);
-	auto &position = routine.getVariable(it->second.Id);
+	if(it != spirvShader->outputBuiltins.end())
+	{
+		assert(it->second.SizeInComponents == 4);
+		auto &position = routine.getVariable(it->second.Id);
 
-	Vector4f pos;
-	pos.x = position[it->second.FirstComponent + 0];
-	pos.y = position[it->second.FirstComponent + 1];
-	pos.z = position[it->second.FirstComponent + 2];
-	pos.w = position[it->second.FirstComponent + 3];
+		Vector4f pos;
+		pos.x = position[it->second.FirstComponent + 0];
+		pos.y = position[it->second.FirstComponent + 1];
+		pos.z = position[it->second.FirstComponent + 2];
+		pos.w = position[it->second.FirstComponent + 3];
 
-	// Projection and viewport transform.
-	Float4 w = As<Float4>(As<Int4>(pos.w) | (As<Int4>(CmpEQ(pos.w, Float4(0.0f))) & As<Int4>(Float4(1.0f))));
-	Float4 rhw = Float4(1.0f) / w;
+		// Projection and viewport transform.
+		Float4 w = As<Float4>(As<Int4>(pos.w) | (As<Int4>(CmpEQ(pos.w, Float4(0.0f))) & As<Int4>(Float4(1.0f))));
+		Float4 rhw = Float4(1.0f) / w;
 
-	Vector4f proj;
-	proj.x = As<Float4>(RoundIntClamped(*Pointer<Float4>(data + OFFSET(DrawData, X0xF)) + pos.x * rhw * *Pointer<Float4>(data + OFFSET(DrawData, WxF))));
-	proj.y = As<Float4>(RoundIntClamped(*Pointer<Float4>(data + OFFSET(DrawData, Y0xF)) + pos.y * rhw * *Pointer<Float4>(data + OFFSET(DrawData, HxF))));
-	proj.z = pos.z * rhw;
-	proj.w = rhw;
+		Vector4f proj;
+		proj.x = As<Float4>(RoundIntClamped(*Pointer<Float4>(data + OFFSET(DrawData, X0xF)) + pos.x * rhw * *Pointer<Float4>(data + OFFSET(DrawData, WxF))));
+		proj.y = As<Float4>(RoundIntClamped(*Pointer<Float4>(data + OFFSET(DrawData, Y0xF)) + pos.y * rhw * *Pointer<Float4>(data + OFFSET(DrawData, HxF))));
+		proj.z = pos.z * rhw;
+		proj.w = rhw;
 
-	transpose4x4(pos.x, pos.y, pos.z, pos.w);
+		transpose4x4(pos.x, pos.y, pos.z, pos.w);
 
-	*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex3 + OFFSET(Vertex, position), 16) = pos.w;
-	*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex2 + OFFSET(Vertex, position), 16) = pos.z;
-	*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex1 + OFFSET(Vertex, position), 16) = pos.y;
-	*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex0 + OFFSET(Vertex, position), 16) = pos.x;
+		*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex3 + OFFSET(Vertex, position), 16) = pos.w;
+		*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex2 + OFFSET(Vertex, position), 16) = pos.z;
+		*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex1 + OFFSET(Vertex, position), 16) = pos.y;
+		*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex0 + OFFSET(Vertex, position), 16) = pos.x;
+
+		*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex3 + OFFSET(Vertex, clipFlags)) = (clipFlags >> 24) & 0x0000000FF;
+		*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex2 + OFFSET(Vertex, clipFlags)) = (clipFlags >> 16) & 0x0000000FF;
+		*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex1 + OFFSET(Vertex, clipFlags)) = (clipFlags >> 8) & 0x0000000FF;
+		*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex0 + OFFSET(Vertex, clipFlags)) = (clipFlags >> 0) & 0x0000000FF;
+
+		transpose4x4(proj.x, proj.y, proj.z, proj.w);
+
+		*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex3 + OFFSET(Vertex, projected), 16) = proj.w;
+		*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex2 + OFFSET(Vertex, projected), 16) = proj.z;
+		*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex1 + OFFSET(Vertex, projected), 16) = proj.y;
+		*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex0 + OFFSET(Vertex, projected), 16) = proj.x;
+	}
 
 	it = spirvShader->outputBuiltins.find(spv::BuiltInPointSize);
 	if(it != spirvShader->outputBuiltins.end())
@@ -598,23 +614,11 @@
 		}
 	}
 
-	*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex3 + OFFSET(Vertex, clipFlags)) = (clipFlags >> 24) & 0x0000000FF;
-	*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex2 + OFFSET(Vertex, clipFlags)) = (clipFlags >> 16) & 0x0000000FF;
-	*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex1 + OFFSET(Vertex, clipFlags)) = (clipFlags >> 8) & 0x0000000FF;
-	*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex0 + OFFSET(Vertex, clipFlags)) = (clipFlags >> 0) & 0x0000000FF;
-
 	*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex3 + OFFSET(Vertex, cullMask)) = -((cullMask >> 3) & 1);
 	*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex2 + OFFSET(Vertex, cullMask)) = -((cullMask >> 2) & 1);
 	*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex1 + OFFSET(Vertex, cullMask)) = -((cullMask >> 1) & 1);
 	*Pointer<Int>(vertexCache + sizeof(Vertex) * cacheIndex0 + OFFSET(Vertex, cullMask)) = -((cullMask >> 0) & 1);
 
-	transpose4x4(proj.x, proj.y, proj.z, proj.w);
-
-	*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex3 + OFFSET(Vertex, projected), 16) = proj.w;
-	*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex2 + OFFSET(Vertex, projected), 16) = proj.z;
-	*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex1 + OFFSET(Vertex, projected), 16) = proj.y;
-	*Pointer<Float4>(vertexCache + sizeof(Vertex) * cacheIndex0 + OFFSET(Vertex, projected), 16) = proj.x;
-
 	for(int i = 0; i < MAX_INTERFACE_COMPONENTS; i += 4)
 	{
 		if(spirvShader->outputs[i + 0].Type != SpirvShader::ATTRIBTYPE_UNUSED ||