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)
{