Enforce OOB requirements for binding with multiple attributes

The spec states that, if any vertex input attribute using a specific
vertex input binding is out of bounds, then all vertex input attributes
using that vertex input binding for that vertex shader invocation are
considered out of bounds.

Affects: dEQP-VK.robustness.vertex_access.*.vertex_incomplete

Components: Vulkan

VK-GL-CTS issue: 848

Change-Id: I6a9222a0b2a53368af361419105793a5301a6bf6
diff --git a/external/vulkancts/modules/vulkan/robustness/vktRobustnessVertexAccessTests.cpp b/external/vulkancts/modules/vulkan/robustness/vktRobustnessVertexAccessTests.cpp
index a0c33f4..c66b914 100644
--- a/external/vulkancts/modules/vulkan/robustness/vktRobustnessVertexAccessTests.cpp
+++ b/external/vulkancts/modules/vulkan/robustness/vktRobustnessVertexAccessTests.cpp
@@ -758,7 +758,7 @@
 	std::ostringstream			logMsg;
 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
 	tcu::TestLog&				log						= m_context.getTestContext().getLog();
-	const int					numChannels				= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
+	const deUint32				numChannels				= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
 	const deUint32				numScalarsPerVertex		= numChannels * 3; // Use 3 identical attributes
 	void*						outDataPtr				= m_outBufferAlloc->getHostPtr();
 	const deUint32				outValueSize			= sizeof(deUint32);
@@ -782,11 +782,12 @@
 		VkDeviceSize		inBufferAllocSize;
 		deUint32			inBufferValueIndex;
 		bool				isOutOfBoundsAccess		= false;
-		const bool			isInstanceRateValue		= ((valueNdx / numChannels) % 3 == 2);
+		const deUint32		attributeIndex			= (valueNdx / numChannels) % 3;
 		const deUint32*		outValuePtr				= (deUint32*)outDataPtr + valueNdx;
 
-		if (isInstanceRateValue)
+		if (attributeIndex == 2)
 		{
+			// Instance rate
 			const deUint32	elementIndex	= valueNdx / (numScalarsPerVertex * m_numVertices); // instance id
 
 			numInBufferValues	= m_numInstanceValues;
@@ -796,6 +797,7 @@
 		}
 		else
 		{
+			// Vertex rate
 			const deUint32	vertexNdx		= valueNdx / numScalarsPerVertex;
 			const deUint32	instanceNdx		= vertexNdx / m_numVertices;
 			const deUint32	elementIndex	= valueNdx / numScalarsPerVertex; // vertex id
@@ -804,6 +806,10 @@
 			inBufferPtr			= m_vertexRateBufferAlloc->getHostPtr();
 			inBufferAllocSize	= m_vertexRateBufferAllocSize;
 			inBufferValueIndex	= (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2);
+
+			// Binding 0 contains two attributes, so bounds checking for attribute 0 must also consider attribute 1 to determine if the binding is out of bounds.
+			if ((attributeIndex == 0) && (numInBufferValues >= numChannels))
+				numInBufferValues -= numChannels;
 		}
 
 		isOutOfBoundsAccess	= (inBufferValueIndex >= numInBufferValues);
@@ -815,8 +821,6 @@
 
 		// Log value information
 		{
-			const deUint32	attributeIndex	= (valueNdx % numScalarsPerVertex) / numChannels;
-
 			// Vertex separator
 			if (valueNdx && valueNdx % numScalarsPerVertex == 0)
 				logMsg << "\n";