Fixed a crash using TransformFeedback with DrawArraysInstanced

When using TransformFeedback with DrawArraysInstanced, a crash
would occur if no varyings were set to use transform feedback
due to a null transform feedback buffer. Added a null pointer
check and an assert to fix this.

Bug b/117080493

Change-Id: Ieb226bfb70ae837bdb206bdbefe84f62dc1f2204
Reviewed-on: https://swiftshader-review.googlesource.com/c/23569
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Corentin Wallez <cwallez@google.com>
diff --git a/src/OpenGL/libGLESv2/Program.cpp b/src/OpenGL/libGLESv2/Program.cpp
index dc64813..cc4c49c 100644
--- a/src/OpenGL/libGLESv2/Program.cpp
+++ b/src/OpenGL/libGLESv2/Program.cpp
@@ -1261,10 +1261,14 @@
 			// In INTERLEAVED_ATTRIBS mode, the values of one or more output variables
 			// written by a vertex shader are written, interleaved, into the buffer object
 			// bound to the first transform feedback binding point (index = 0).
-			sw::Resource* resource = transformFeedbackBuffers[0].get()->getResource();
+			sw::Resource* resource = transformFeedbackBuffers[0].get() ?
+			                         transformFeedbackBuffers[0].get()->getResource() :
+			                         nullptr;
 			int componentStride = static_cast<int>(totalLinkedVaryingsComponents);
 			int baseOffset = transformFeedbackBuffers[0].getOffset() + (transformFeedback->vertexOffset() * componentStride * sizeof(float));
 			maxVaryings = sw::min(maxVaryings, (unsigned int)sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
+			ASSERT(resource || (maxVaryings == 0));
+
 			int totalComponents = 0;
 			for(unsigned int index = 0; index < maxVaryings; ++index)
 			{
diff --git a/tests/GLESUnitTests/unittests.cpp b/tests/GLESUnitTests/unittests.cpp
index a1ea0b6..4829b5d 100644
--- a/tests/GLESUnitTests/unittests.cpp
+++ b/tests/GLESUnitTests/unittests.cpp
@@ -950,6 +950,50 @@
 	Uninitialize();
 }
 
+TEST_F(SwiftShaderTest, TransformFeedback_DrawArraysInstanced)
+{
+	Initialize(3, false);
+
+	const char * data0[] =

+	{

+		"#version 300 es\n"

+		"in mediump vec2 vary;"

+		"out mediump vec4 color;"

+		"void main()"

+		"{\t"

+			"color = vec4(vary, 0.0, 1.0);"

+		"}"

+	};

+	const char * data1[] =

+	{

+		"#version 300 es\n"

+		"layout(location=0) in mediump vec2 pos;"

+		"out mediump vec2 vary;"

+		"void main()"

+		"{\t"

+			"vary = pos;\t"

+			"gl_Position = vec4(pos, 0.0, 1.0);"

+		"}"

+	};

+

+	GLuint vert = glCreateShader(GL_VERTEX_SHADER);

+	GLuint frag = glCreateShader(GL_FRAGMENT_SHADER);

+	GLuint program = glCreateProgram();

+

+	glShaderSource(frag, 1, data0, (const GLint *)0);

+	glAttachShader(program, vert);

+	glCompileShader(frag);

+	glAttachShader(program, frag);

+	glShaderSource(vert, 1, data1, (const GLint *)0);

+	glCompileShader(vert);

+	glLinkProgram(program);

+	glUseProgram(program);

+	glBeginTransformFeedback(GL_POINTS);

+	glDrawArraysInstanced(GL_POINTS, 0, 1, 1);
+
+	Uninitialize();
+}
+
 // Test conditions that should result in a GL_OUT_OF_MEMORY and not crash
 TEST_F(SwiftShaderTest, OutOfMemory)
 {