Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c8f25d9

Browse files
committed
Don't try to render out-of-bounds viewports
If a viewport is outside maximum bounds of the render buffer, then there's nothing to render, unless transform feedback is active. If transform feedback is active, then we zero out the viewport. This is to prevent an overflow in viewport-dependent calculations. Bug chromium:969353 Change-Id: Ibc65447ca2b46e942b9934304a56b90f261e2bf1 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/33068 Reviewed-by: Alexis Hétu <sugoi@google.com> Tested-by: Sean Risser <srisser@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
1 parent a7edc1c commit c8f25d9

File tree

3 files changed

+132
-27
lines changed

3 files changed

+132
-27
lines changed

src/OpenGL/libGLESv2/Context.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2797,6 +2797,23 @@ bool Context::applyRenderTarget()
27972797
viewport.minZ = zNear;
27982798
viewport.maxZ = zFar;
27992799

2800+
if (viewport.x0 > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
2801+
viewport.y0 > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
2802+
{
2803+
TransformFeedback* transformFeedback = getTransformFeedback();
2804+
if (!transformFeedback->isActive() || transformFeedback->isPaused())
2805+
{
2806+
return false;
2807+
}
2808+
else
2809+
{
2810+
viewport.x0 = 0;
2811+
viewport.y0 = 0;
2812+
viewport.width = 0;
2813+
viewport.height = 0;
2814+
}
2815+
}
2816+
28002817
device->setViewport(viewport);
28012818

28022819
applyScissor(width, height);

src/OpenGL/libGLESv2/Device.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ namespace es2
707707

708708
bool Device::bindResources()
709709
{
710-
if(!bindViewport())
710+
if(!bindViewport() && !context->transformFeedbackEnabled)
711711
{
712712
return false; // Zero-area target region
713713
}

tests/GLESUnitTests/unittests.cpp

Lines changed: 114 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -233,45 +233,58 @@ class SwiftShaderTest : public testing::Test
233233
GLuint fragmentShader;
234234
};
235235

236-
ProgramHandles createProgram(const std::string& vs, const std::string& fs)
236+
GLuint MakeShader(const std::string &source, GLenum shaderType)
237237
{
238+
GLuint shader = glCreateShader(shaderType);
239+
const char *c_source[1] = { source.c_str() };
240+
glShaderSource(shader, 1, c_source, nullptr);
241+
glCompileShader(shader);
242+
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
243+
238244
GLchar buf[1024];
245+
GLint compileStatus = 0;
246+
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
247+
glGetShaderInfoLog(shader, sizeof(buf), nullptr, buf);
248+
EXPECT_EQ(compileStatus, GL_TRUE) << "Compile status: " << std::endl << buf;
239249

240-
ProgramHandles ph;
241-
ph.program = glCreateProgram();
242-
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
250+
return shader;
251+
}
243252

244-
ph.vertexShader = glCreateShader(GL_VERTEX_SHADER);
245-
const char* vsSource[1] = { vs.c_str() };
246-
glShaderSource(ph.vertexShader, 1, vsSource, nullptr);
247-
glCompileShader(ph.vertexShader);
248-
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
249-
GLint vsCompileStatus = 0;
250-
glGetShaderiv(ph.vertexShader, GL_COMPILE_STATUS, &vsCompileStatus);
251-
glGetShaderInfoLog(ph.vertexShader, sizeof(buf), nullptr, buf);
252-
EXPECT_EQ(vsCompileStatus, GL_TRUE) << "Compile status: " << std::endl << buf;
253+
GLuint MakeProgram(GLuint vs, GLuint fs)
254+
{
255+
GLuint program;
253256

254-
ph.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
255-
const char* fsSource[1] = { fs.c_str() };
256-
glShaderSource(ph.fragmentShader, 1, fsSource, nullptr);
257-
glCompileShader(ph.fragmentShader);
257+
program = glCreateProgram();
258258
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
259-
GLint fsCompileStatus = 0;
260-
glGetShaderiv(ph.fragmentShader, GL_COMPILE_STATUS, &fsCompileStatus);
261-
glGetShaderInfoLog(ph.fragmentShader, sizeof(buf), nullptr, buf);
262-
EXPECT_EQ(fsCompileStatus, GL_TRUE) << "Compile status: " << std::endl << buf;
263259

264-
glAttachShader(ph.program, ph.vertexShader);
265-
glAttachShader(ph.program, ph.fragmentShader);
266-
glLinkProgram(ph.program);
260+
glAttachShader(program, vs);
261+
glAttachShader(program, fs);
267262
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
268263

264+
return program;
265+
}
266+
267+
void LinkProgram(GLuint program)
268+
{
269+
GLchar buf[1024];
270+
glLinkProgram(program);
271+
269272
GLint linkStatus = 0;
270-
glGetProgramiv(ph.program, GL_LINK_STATUS, &linkStatus);
271-
glGetProgramInfoLog(ph.program, sizeof(buf), nullptr, buf);
273+
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
274+
glGetProgramInfoLog(program, sizeof(buf), nullptr, buf);
272275
EXPECT_NE(linkStatus, 0) << "Link status: " << std::endl << buf;
273276

274277
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
278+
}
279+
280+
281+
ProgramHandles createProgram(const std::string& vs, const std::string& fs)
282+
{
283+
ProgramHandles ph;
284+
ph.vertexShader = MakeShader(vs, GL_VERTEX_SHADER);
285+
ph.fragmentShader = MakeShader(fs, GL_FRAGMENT_SHADER);
286+
ph.program = MakeProgram(ph.vertexShader, ph.fragmentShader);
287+
LinkProgram(ph.program);
275288

276289
return ph;
277290
}
@@ -1206,6 +1219,81 @@ TEST_F(SwiftShaderTest, TransformFeedback_DrawArraysInstanced)
12061219
Uninitialize();
12071220
}
12081221

1222+
TEST_F(SwiftShaderTest, TransformFeedback_BadViewport)
1223+
{
1224+
Initialize(3, false);
1225+
1226+
GLuint tfBuffer;
1227+
glGenBuffers(1, &tfBuffer);
1228+
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tfBuffer);
1229+
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1 << 12, nullptr, GL_STATIC_DRAW);
1230+
1231+
std::string vsSource =
1232+
R"(#version 300 es
1233+
in vec4 a_position;
1234+
void main()
1235+
{
1236+
gl_Position = a_position;
1237+
})";
1238+
std::string fsSource =
1239+
R"(#version 300 es
1240+
precision highp float;
1241+
out vec4 my_FragColor;
1242+
void main()
1243+
{
1244+
my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
1245+
})";
1246+
1247+
const char *varyings[] = { "gl_Position" };
1248+
1249+
GLuint vs = MakeShader(vsSource, GL_VERTEX_SHADER);
1250+
GLuint fs = MakeShader(fsSource, GL_FRAGMENT_SHADER);
1251+
GLuint program = MakeProgram(vs, fs);
1252+
1253+
glTransformFeedbackVaryings(program, 1,
1254+
&varyings[0], GL_INTERLEAVED_ATTRIBS);
1255+
LinkProgram(program);
1256+
glUseProgram(program);
1257+
1258+
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer);
1259+
glBeginTransformFeedback(GL_TRIANGLES);
1260+
1261+
GLuint primitivesWrittenQuery = 0;
1262+
glGenQueries(1, &primitivesWrittenQuery);
1263+
glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery);
1264+
1265+
glViewport(0, 10000000, 300, 300);
1266+
1267+
GLint positionLocation = glGetAttribLocation(program, "a_position");
1268+
GLfloat quadVertices[] = {
1269+
-1.0f, 1.0f, 0.5f,
1270+
-1.0f, -1.0f, 0.5f,
1271+
1.0f, -1.0f, 0.5f,
1272+
-1.0f, 1.0f, 0.5f,
1273+
1.0f, -1.0f, 0.5f,
1274+
1.0f, 1.0f, 0.5f,
1275+
};
1276+
1277+
glBindBuffer(GL_ARRAY_BUFFER, 0);
1278+
1279+
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, &quadVertices[0]);
1280+
1281+
glDrawArrays(GL_TRIANGLES, 0, 6);
1282+
glDisableVertexAttribArray(positionLocation);
1283+
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
1284+
1285+
glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
1286+
glEndTransformFeedback();
1287+
1288+
GLuint primitivesWritten = 0;
1289+
glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten);
1290+
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1291+
1292+
EXPECT_EQ(2u, primitivesWritten);
1293+
1294+
Uninitialize();
1295+
}
1296+
12091297
// Test conditions that should result in a GL_OUT_OF_MEMORY and not crash
12101298
TEST_F(SwiftShaderTest, OutOfMemory)
12111299
{

0 commit comments

Comments
 (0)