123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include <GLES2/gl2.h>
- #include <GLES2/gl2ext.h>
- #include <GLES2/gl2extchromium.h>
- #include <stdint.h>
- #include "gpu/command_buffer/tests/gl_manager.h"
- #include "gpu/command_buffer/tests/gl_test_utils.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #define SHADER(Src) #Src
- namespace gpu {
- class BindUniformLocationTest : public testing::TestWithParam<bool> {
- protected:
- static const GLsizei kResolution = 4;
- void SetUp() override {
- GLManager::Options options;
- options.size = gfx::Size(kResolution, kResolution);
- options.force_shader_name_hashing = GetParam();
- gl_.Initialize(options);
- }
- void TearDown() override { gl_.Destroy(); }
- GLManager gl_;
- };
- TEST_P(BindUniformLocationTest, Basic) {
- ASSERT_TRUE(
- GLTestHelper::HasExtension("GL_CHROMIUM_bind_uniform_location"));
- static const char* v_shader_str = SHADER(
- attribute vec4 a_position;
- void main()
- {
- gl_Position = a_position;
- }
- );
- static const char* f_shader_str = SHADER(
- 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;
- }
- );
- GLint color_a_location = 3;
- GLint color_b_location = 10;
- GLint color_c_location = 5;
- GLuint vertex_shader = GLTestHelper::LoadShader(
- GL_VERTEX_SHADER, v_shader_str);
- GLuint fragment_shader = GLTestHelper::LoadShader(
- GL_FRAGMENT_SHADER, f_shader_str);
- GLuint program = glCreateProgram();
- glBindUniformLocationCHROMIUM(program, color_a_location, "u_colorA");
- glBindUniformLocationCHROMIUM(program, color_b_location, "u_colorB[0]");
- glBindUniformLocationCHROMIUM(program, color_c_location, "u_colorC");
- glAttachShader(program, vertex_shader);
- glAttachShader(program, fragment_shader);
- // Link the program
- glLinkProgram(program);
- // Check the link status
- GLint linked = 0;
- glGetProgramiv(program, GL_LINK_STATUS, &linked);
- EXPECT_EQ(1, linked);
- GLint position_loc = glGetAttribLocation(program, "a_position");
- GLTestHelper::SetupUnitQuad(position_loc);
- glUseProgram(program);
- static const float color_b[] = {
- 0.0f, 0.50f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.75f, 0.0f,
- };
- glUniform4f(color_a_location, 0.25f, 0.0f, 0.0f, 0.0f);
- glUniform4fv(color_b_location, 2, color_b);
- glUniform4f(color_c_location, 0.0f, 0.0f, 0.0f, 1.0f);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- static const uint8_t expected[] = {64, 128, 192, 255};
- EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, kResolution, kResolution, 1,
- expected, nullptr));
- GLTestHelper::CheckGLError("no errors", __LINE__);
- }
- TEST_P(BindUniformLocationTest, ConflictsDetection) {
- ASSERT_TRUE(
- GLTestHelper::HasExtension("GL_CHROMIUM_bind_uniform_location"));
- static const char* v_shader_str = SHADER(
- attribute vec4 a_position;
- void main()
- {
- gl_Position = a_position;
- }
- );
- static const char* f_shader_str = SHADER(
- precision mediump float;
- uniform vec4 u_colorA;
- uniform vec4 u_colorB;
- void main()
- {
- gl_FragColor = u_colorA + u_colorB;
- }
- );
- GLint color_a_location = 3;
- GLint color_b_location = 4;
- GLuint vertex_shader = GLTestHelper::LoadShader(
- GL_VERTEX_SHADER, v_shader_str);
- GLuint fragment_shader = GLTestHelper::LoadShader(
- GL_FRAGMENT_SHADER, f_shader_str);
- GLuint program = glCreateProgram();
- glAttachShader(program, vertex_shader);
- glAttachShader(program, fragment_shader);
- glBindUniformLocationCHROMIUM(program, color_a_location, "u_colorA");
- // Bind u_colorB to location a, causing conflicts, link should fail.
- glBindUniformLocationCHROMIUM(program, color_a_location, "u_colorB");
- glLinkProgram(program);
- GLint linked = 0;
- glGetProgramiv(program, GL_LINK_STATUS, &linked);
- EXPECT_EQ(0, linked);
- // Bind u_colorB to location b, no conflicts, link should succeed.
- glBindUniformLocationCHROMIUM(program, color_b_location, "u_colorB");
- glLinkProgram(program);
- linked = 0;
- glGetProgramiv(program, GL_LINK_STATUS, &linked);
- EXPECT_EQ(1, linked);
- GLTestHelper::CheckGLError("no errors", __LINE__);
- }
- TEST_P(BindUniformLocationTest, Compositor) {
- ASSERT_TRUE(
- GLTestHelper::HasExtension("GL_CHROMIUM_bind_uniform_location"));
- static const char* v_shader_str = SHADER(
- 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;
- }
- );
- static const char* f_shader_str = SHADER(
- 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;
- }
- );
- int counter = 6;
- int matrix_location = counter++;
- int color_a_location = counter++;
- int color_b_location = counter++;
- int alpha_location = counter++;
- int multiplier_location = counter++;
- int color_c_location = counter++;
- GLuint vertex_shader = GLTestHelper::LoadShader(
- GL_VERTEX_SHADER, v_shader_str);
- GLuint fragment_shader = GLTestHelper::LoadShader(
- GL_FRAGMENT_SHADER, f_shader_str);
- GLuint program = glCreateProgram();
- glBindUniformLocationCHROMIUM(program, matrix_location, "matrix");
- glBindUniformLocationCHROMIUM(program, color_a_location, "color_a");
- glBindUniformLocationCHROMIUM(program, color_b_location, "color_b");
- glBindUniformLocationCHROMIUM(program, alpha_location, "alpha");
- glBindUniformLocationCHROMIUM(program, multiplier_location, "multiplier");
- glBindUniformLocationCHROMIUM(program, color_c_location, "color_c");
- glAttachShader(program, vertex_shader);
- glAttachShader(program, fragment_shader);
- // Link the program
- glLinkProgram(program);
- // Check the link status
- GLint linked = 0;
- glGetProgramiv(program, GL_LINK_STATUS, &linked);
- EXPECT_EQ(1, linked);
- GLint position_loc = glGetAttribLocation(program, "a_position");
- GLTestHelper::SetupUnitQuad(position_loc);
- glUseProgram(program);
- static const float color_a[] = {
- 0.1f, 0.1f, 0.1f, 0.1f,
- 0.1f, 0.1f, 0.1f, 0.1f,
- };
- static const float color_c[] = {
- 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(matrix_location, 1, false, identity);
- glUniform2fv(color_a_location, 4, color_a);
- glUniform4f(color_b_location, 0.2f, 0.2f, 0.2f, 0.2f);
- glUniform1f(alpha_location, 0.8f);
- glUniform4f(multiplier_location, 0.5f, 0.5f, 0.5f, 0.5f);
- glUniform3fv(color_c_location, 8, color_c);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- static const uint8_t expected[] = {204, 204, 204, 204};
- EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, kResolution, kResolution, 1,
- expected, nullptr));
- GLTestHelper::CheckGLError("no errors", __LINE__);
- }
- TEST_P(BindUniformLocationTest, UnusedUniformUpdate) {
- ASSERT_TRUE(GLTestHelper::HasExtension("GL_CHROMIUM_bind_uniform_location"));
- // clang-format off
- static const char* kVertexShaderString = SHADER(
- attribute vec4 a_position;
- void main() {
- gl_Position = a_position;
- }
- );
- static const char* kFragmentShaderString = SHADER(
- 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 kColorULocation = 1;
- const GLint kNonexistingLocation = 5;
- const GLint kUnboundLocation = 6;
- GLuint vertex_shader =
- GLTestHelper::LoadShader(GL_VERTEX_SHADER, kVertexShaderString);
- GLuint fragment_shader =
- GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShaderString);
- GLuint program = glCreateProgram();
- glBindUniformLocationCHROMIUM(program, kColorULocation, "u_colorU");
- // The non-existing uniform should behave like existing, but optimized away
- // uniform.
- glBindUniformLocationCHROMIUM(program, kNonexistingLocation, "nonexisting");
- // Let A and C be assigned automatic locations.
- glAttachShader(program, vertex_shader);
- glAttachShader(program, fragment_shader);
- glLinkProgram(program);
- GLint linked = 0;
- glGetProgramiv(program, GL_LINK_STATUS, &linked);
- EXPECT_EQ(1, linked);
- glUseProgram(program);
- // No errors on bound locations, since caller does not know
- // if the driver optimizes them away or not.
- glUniform1f(kColorULocation, 0.25f);
- EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- // No errors on bound locations of names that do not exist
- // in the shader. Otherwise it would be inconsistent wrt the
- // optimization case.
- glUniform1f(kNonexistingLocation, 0.25f);
- EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- // The above are equal to updating -1.
- glUniform1f(-1, 0.25f);
- EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- // No errors when updating with other type either.
- // The type can not be known with the non-existing case.
- glUniform2f(kColorULocation, 0.25f, 0.25f);
- EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- glUniform2f(kNonexistingLocation, 0.25f, 0.25f);
- EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- glUniform2f(-1, 0.25f, 0.25f);
- EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- // Ensure that driver or ANGLE has optimized the variable
- // away and the test tests what it is supposed to.
- EXPECT_EQ(-1, glGetUniformLocation(program, "u_colorU"));
- // The bound location gets marked as used and the driver
- // does not allocate other variables to that location.
- EXPECT_NE(kColorULocation, glGetUniformLocation(program, "u_colorA"));
- EXPECT_NE(kColorULocation, glGetUniformLocation(program, "u_colorC"));
- EXPECT_NE(kNonexistingLocation, glGetUniformLocation(program, "u_colorA"));
- EXPECT_NE(kNonexistingLocation, glGetUniformLocation(program, "u_colorC"));
- // Unintuitive: while specifying value works, getting the value does not.
- GLfloat get_result = 0.0f;
- glGetUniformfv(program, kColorULocation, &get_result);
- EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
- glGetUniformfv(program, kNonexistingLocation, &get_result);
- EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
- glGetUniformfv(program, -1, &get_result);
- EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
- // Updating an unbound, non-existing location still causes
- // an error.
- glUniform1f(kUnboundLocation, 0.25f);
- EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
- }
- // Test for a bug where using a sampler caused GL error if the program 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) {
- enum {
- kTexLocation = 54
- };
- // clang-format off
- static const char* vertexShaderString = SHADER(
- void main() {
- gl_Position = vec4(0);
- }
- );
- static const char* fragmentShaderString = SHADER(
- uniform sampler2D tex;
- void main() {
- gl_FragColor = texture2D(tex, vec2(1));
- }
- );
- // clang-format on
- GLuint vs = GLTestHelper::CompileShader(GL_VERTEX_SHADER, vertexShaderString);
- GLuint fs = GLTestHelper::CompileShader(GL_FRAGMENT_SHADER,
- fragmentShaderString);
- GLuint program = glCreateProgram();
- glBindUniformLocationCHROMIUM(program, kTexLocation, "tex");
- glAttachShader(program, vs);
- glAttachShader(program, fs);
- glLinkProgram(program);
- GLint linked = 0;
- glGetProgramiv(program, GL_LINK_STATUS, &linked);
- EXPECT_NE(0, linked);
- glUseProgram(program);
- glUniform1i(kTexLocation, 0);
- EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- }
- INSTANTIATE_TEST_SUITE_P(WithAndWithoutShaderNameMapping,
- BindUniformLocationTest,
- ::testing::Bool());
- } // namespace gpu
|