summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/tests/gl_tests/BindUniformLocationTest.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /gfx/angle/src/tests/gl_tests/BindUniformLocationTest.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/angle/src/tests/gl_tests/BindUniformLocationTest.cpp')
-rwxr-xr-xgfx/angle/src/tests/gl_tests/BindUniformLocationTest.cpp484
1 files changed, 484 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/gl_tests/BindUniformLocationTest.cpp b/gfx/angle/src/tests/gl_tests/BindUniformLocationTest.cpp
new file mode 100755
index 000000000..732a11068
--- /dev/null
+++ b/gfx/angle/src/tests/gl_tests/BindUniformLocationTest.cpp
@@ -0,0 +1,484 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BindUniformLocationTest.cpp : Tests of the GL_CHROMIUM_bind_uniform_location extension.
+
+#include "test_utils/ANGLETest.h"
+
+#include <cmath>
+
+using namespace angle;
+
+namespace
+{
+
+class BindUniformLocationTest : public ANGLETest
+{
+ protected:
+ BindUniformLocationTest()
+ {
+ setWindowWidth(128);
+ setWindowHeight(128);
+ setConfigRedBits(8);
+ setConfigGreenBits(8);
+ setConfigBlueBits(8);
+ setConfigAlphaBits(8);
+ }
+
+ void SetUp() override
+ {
+ ANGLETest::SetUp();
+ mBindUniformLocation = reinterpret_cast<PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC>(
+ eglGetProcAddress("glBindUniformLocationCHROMIUM"));
+ }
+
+ void TearDown() override
+ {
+ if (mProgram != 0)
+ {
+ glDeleteProgram(mProgram);
+ }
+ ANGLETest::TearDown();
+ }
+
+ typedef void(GL_APIENTRYP PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC)(GLuint mProgram,
+ GLint location,
+ const GLchar *name);
+ PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC mBindUniformLocation = nullptr;
+
+ GLuint mProgram = 0;
+};
+
+// Test basic functionality of GL_CHROMIUM_bind_uniform_location
+TEST_P(BindUniformLocationTest, Basic)
+{
+ if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+ {
+ std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+ << std::endl;
+ return;
+ }
+
+ ASSERT_NE(mBindUniformLocation, nullptr);
+
+ // clang-format off
+ const std::string vsSource = SHADER_SOURCE
+ (
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+ );
+
+ const std::string fsSource = SHADER_SOURCE
+ (
+ precision mediump float;
+ uniform vec4 u_colorC;
+ uniform vec4 u_colorB[2];
+ uniform vec4 u_colorA;
+ void main()
+ {
+ gl_FragColor = u_colorA + u_colorB[0] + u_colorB[1] + u_colorC;
+ }
+ );
+ // clang-format on
+
+ GLint colorALocation = 3;
+ GLint colorBLocation = 10;
+ GLint colorCLocation = 5;
+
+ GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+ GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+ mProgram = glCreateProgram();
+
+ mBindUniformLocation(mProgram, colorALocation, "u_colorA");
+ mBindUniformLocation(mProgram, colorBLocation, "u_colorB[0]");
+ mBindUniformLocation(mProgram, colorCLocation, "u_colorC");
+
+ glAttachShader(mProgram, vs);
+ glDeleteShader(vs);
+
+ glAttachShader(mProgram, fs);
+ glDeleteShader(fs);
+
+ // Link the mProgram
+ glLinkProgram(mProgram);
+ // Check the link status
+ GLint linked = 0;
+ glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+ ASSERT_EQ(1, linked);
+
+ glUseProgram(mProgram);
+
+ static const float colorB[] = {
+ 0.0f, 0.50f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.0f,
+ };
+
+ glUniform4f(colorALocation, 0.25f, 0.0f, 0.0f, 0.0f);
+ glUniform4fv(colorBLocation, 2, colorB);
+ glUniform4f(colorCLocation, 0.0f, 0.0f, 0.0f, 1.0f);
+
+ drawQuad(mProgram, "a_position", 0.5f);
+
+ EXPECT_GL_NO_ERROR();
+ EXPECT_PIXEL_NEAR(0, 0, 64, 128, 192, 255, 1.0);
+}
+
+// Test that conflicts are detected when two uniforms are bound to the same location
+TEST_P(BindUniformLocationTest, ConflictsDetection)
+{
+ if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+ {
+ std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+ << std::endl;
+ return;
+ }
+
+ ASSERT_NE(nullptr, mBindUniformLocation);
+
+ // clang-format off
+ const std::string vsSource = SHADER_SOURCE
+ (
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+ );
+
+ const std::string fsSource = SHADER_SOURCE
+ (
+ precision mediump float;
+ uniform vec4 u_colorA;
+ uniform vec4 u_colorB;
+ void main()
+ {
+ gl_FragColor = u_colorA + u_colorB;
+ }
+ );
+ // clang-format on
+
+ GLint colorALocation = 3;
+ GLint colorBLocation = 4;
+
+ GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+ GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+ mProgram = glCreateProgram();
+ glAttachShader(mProgram, vs);
+ glDeleteShader(vs);
+ glAttachShader(mProgram, fs);
+ glDeleteShader(fs);
+
+ mBindUniformLocation(mProgram, colorALocation, "u_colorA");
+ // Bind u_colorB to location a, causing conflicts, link should fail.
+ mBindUniformLocation(mProgram, colorALocation, "u_colorB");
+ glLinkProgram(mProgram);
+ GLint linked = 0;
+ glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+ ASSERT_EQ(0, linked);
+
+ // Bind u_colorB to location b, no conflicts, link should succeed.
+ mBindUniformLocation(mProgram, colorBLocation, "u_colorB");
+ glLinkProgram(mProgram);
+ linked = 0;
+ glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+ EXPECT_EQ(1, linked);
+}
+
+// Test a use case of the chromium compositor
+TEST_P(BindUniformLocationTest, Compositor)
+{
+ if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+ {
+ std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+ << std::endl;
+ return;
+ }
+
+ ASSERT_NE(nullptr, mBindUniformLocation);
+
+ // clang-format off
+ const std::string vsSource = SHADER_SOURCE
+ (
+ attribute vec4 a_position;
+ attribute vec2 a_texCoord;
+ uniform mat4 matrix;
+ uniform vec2 color_a[4];
+ uniform vec4 color_b;
+ varying vec4 v_color;
+ void main()
+ {
+ v_color.xy = color_a[0] + color_a[1];
+ v_color.zw = color_a[2] + color_a[3];
+ v_color += color_b;
+ gl_Position = matrix * a_position;
+ }
+ );
+
+ const std::string fsSource = SHADER_SOURCE
+ (
+ precision mediump float;
+ varying vec4 v_color;
+ uniform float alpha;
+ uniform vec4 multiplier;
+ uniform vec3 color_c[8];
+ void main()
+ {
+ vec4 color_c_sum = vec4(0.0);
+ color_c_sum.xyz += color_c[0];
+ color_c_sum.xyz += color_c[1];
+ color_c_sum.xyz += color_c[2];
+ color_c_sum.xyz += color_c[3];
+ color_c_sum.xyz += color_c[4];
+ color_c_sum.xyz += color_c[5];
+ color_c_sum.xyz += color_c[6];
+ color_c_sum.xyz += color_c[7];
+ color_c_sum.w = alpha;
+ color_c_sum *= multiplier;
+ gl_FragColor = v_color + color_c_sum;
+ }
+ );
+ // clang-format on
+
+ int counter = 6;
+ int matrixLocation = counter++;
+ int colorALocation = counter++;
+ int colorBLocation = counter++;
+ int alphaLocation = counter++;
+ int multiplierLocation = counter++;
+ int colorCLocation = counter++;
+
+ GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+ GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+ mProgram = glCreateProgram();
+
+ mBindUniformLocation(mProgram, matrixLocation, "matrix");
+ mBindUniformLocation(mProgram, colorALocation, "color_a");
+ mBindUniformLocation(mProgram, colorBLocation, "color_b");
+ mBindUniformLocation(mProgram, alphaLocation, "alpha");
+ mBindUniformLocation(mProgram, multiplierLocation, "multiplier");
+ mBindUniformLocation(mProgram, colorCLocation, "color_c");
+
+ glAttachShader(mProgram, vs);
+ glDeleteShader(vs);
+ glAttachShader(mProgram, fs);
+ glDeleteShader(fs);
+
+ // Link the mProgram
+ glLinkProgram(mProgram);
+ // Check the link status
+ GLint linked = 0;
+ glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+ ASSERT_EQ(1, linked);
+
+ glUseProgram(mProgram);
+
+ static const float colorA[] = {
+ 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
+ };
+
+ static const float colorC[] = {
+ 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
+ 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
+ };
+
+ static const float identity[] = {
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
+ };
+
+ glUniformMatrix4fv(matrixLocation, 1, false, identity);
+ glUniform2fv(colorALocation, 4, colorA);
+ glUniform4f(colorBLocation, 0.2f, 0.2f, 0.2f, 0.2f);
+ glUniform1f(alphaLocation, 0.8f);
+ glUniform4f(multiplierLocation, 0.5f, 0.5f, 0.5f, 0.5f);
+ glUniform3fv(colorCLocation, 8, colorC);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ drawQuad(mProgram, "a_position", 0.5f);
+
+ EXPECT_PIXEL_EQ(0, 0, 204, 204, 204, 204);
+}
+
+// Test that unused uniforms don't conflict when bound to the same location
+TEST_P(BindUniformLocationTest, UnusedUniformUpdate)
+{
+ if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+ {
+ std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+ << std::endl;
+ return;
+ }
+
+ ASSERT_NE(nullptr, mBindUniformLocation);
+
+ // clang-format off
+ const std::string vsSource = SHADER_SOURCE
+ (
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+ );
+
+ const std::string fsSource = SHADER_SOURCE
+ (
+ precision mediump float;
+ uniform vec4 u_colorA;
+ uniform float u_colorU;
+ uniform vec4 u_colorC;
+ void main()
+ {
+ gl_FragColor = u_colorA + u_colorC;
+ }
+ );
+ // clang-format on
+
+ const GLint colorULocation = 1;
+ const GLint nonexistingLocation = 5;
+ const GLint unboundLocation = 6;
+
+ GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+ GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+ mProgram = glCreateProgram();
+ mBindUniformLocation(mProgram, colorULocation, "u_colorU");
+ // The non-existing uniform should behave like existing, but optimized away
+ // uniform.
+ mBindUniformLocation(mProgram, nonexistingLocation, "nonexisting");
+ // Let A and C be assigned automatic locations.
+ glAttachShader(mProgram, vs);
+ glDeleteShader(vs);
+ glAttachShader(mProgram, fs);
+ glDeleteShader(fs);
+ glLinkProgram(mProgram);
+ GLint linked = 0;
+ glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+ ASSERT_EQ(1, linked);
+ glUseProgram(mProgram);
+
+ // No errors on bound locations, since caller does not know
+ // if the driver optimizes them away or not.
+ glUniform1f(colorULocation, 0.25f);
+ EXPECT_GL_NO_ERROR();
+
+ // No errors on bound locations of names that do not exist
+ // in the shader. Otherwise it would be inconsistent wrt the
+ // optimization case.
+ glUniform1f(nonexistingLocation, 0.25f);
+ EXPECT_GL_NO_ERROR();
+
+ // The above are equal to updating -1.
+ glUniform1f(-1, 0.25f);
+ EXPECT_GL_NO_ERROR();
+
+ // No errors when updating with other type either.
+ // The type can not be known with the non-existing case.
+ glUniform2f(colorULocation, 0.25f, 0.25f);
+ EXPECT_GL_NO_ERROR();
+ glUniform2f(nonexistingLocation, 0.25f, 0.25f);
+ EXPECT_GL_NO_ERROR();
+ glUniform2f(-1, 0.25f, 0.25f);
+ EXPECT_GL_NO_ERROR();
+
+ // Ensure that driver or ANGLE has optimized the variable
+ // away and the test tests what it is supposed to.
+ EXPECT_EQ(-1, glGetUniformLocation(mProgram, "u_colorU"));
+
+ // The bound location gets marked as used and the driver
+ // does not allocate other variables to that location.
+ EXPECT_NE(colorULocation, glGetUniformLocation(mProgram, "u_colorA"));
+ EXPECT_NE(colorULocation, glGetUniformLocation(mProgram, "u_colorC"));
+ EXPECT_NE(nonexistingLocation, glGetUniformLocation(mProgram, "u_colorA"));
+ EXPECT_NE(nonexistingLocation, glGetUniformLocation(mProgram, "u_colorC"));
+
+ // Unintuitive: while specifying value works, getting the value does not.
+ GLfloat getResult = 0.0f;
+ glGetUniformfv(mProgram, colorULocation, &getResult);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+ glGetUniformfv(mProgram, nonexistingLocation, &getResult);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+ glGetUniformfv(mProgram, -1, &getResult);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+ // Updating an unbound, non-existing location still causes
+ // an error.
+ glUniform1f(unboundLocation, 0.25f);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test for a bug where using a sampler caused GL error if the mProgram had
+// uniforms that were optimized away by the driver. This was only a problem with
+// glBindUniformLocationCHROMIUM implementation. This could be reproed by
+// binding the sampler to a location higher than the amount of active uniforms.
+TEST_P(BindUniformLocationTest, UseSamplerWhenUnusedUniforms)
+{
+ if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
+ {
+ std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
+ << std::endl;
+ return;
+ }
+
+ ASSERT_NE(nullptr, mBindUniformLocation);
+
+ // clang-format off
+ const std::string vsSource = SHADER_SOURCE
+ (
+ void main()
+ {
+ gl_Position = vec4(0);
+ }
+ );
+
+ const std::string fsSource = SHADER_SOURCE
+ (
+ uniform sampler2D tex;
+ void main()
+ {
+ gl_FragColor = texture2D(tex, vec2(1));
+ }
+ );
+ // clang-format on
+
+ const GLuint texLocation = 54;
+
+ GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
+ GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
+
+ mProgram = glCreateProgram();
+ mBindUniformLocation(mProgram, texLocation, "tex");
+
+ glAttachShader(mProgram, vs);
+ glDeleteShader(vs);
+ glAttachShader(mProgram, fs);
+ glDeleteShader(fs);
+
+ glLinkProgram(mProgram);
+
+ GLint linked = 0;
+ glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
+ EXPECT_NE(0, linked);
+ glUseProgram(mProgram);
+ glUniform1i(texLocation, 0);
+ EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(BindUniformLocationTest,
+ ES2_D3D9(),
+ ES2_D3D11(),
+ ES2_D3D11_FL9_3(),
+ ES2_OPENGL(),
+ ES2_OPENGLES());
+
+} // namespace