| // |
| // 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(); |
| } |
| |
| // Test for binding a statically used uniform to the same location as a non-statically used uniform. |
| // This is valid according to the extension spec. |
| TEST_P(BindUniformLocationTest, SameLocationForUsedAndUnusedUniform) |
| { |
| 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 |
| ( |
| precision mediump float; |
| uniform vec4 a; |
| uniform vec4 b; |
| void main() |
| { |
| gl_FragColor = a; |
| } |
| ); |
| // clang-format on |
| |
| const GLuint location = 54; |
| |
| GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource); |
| GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource); |
| |
| mProgram = glCreateProgram(); |
| mBindUniformLocation(mProgram, location, "a"); |
| mBindUniformLocation(mProgram, location, "b"); |
| |
| glAttachShader(mProgram, vs); |
| glDeleteShader(vs); |
| glAttachShader(mProgram, fs); |
| glDeleteShader(fs); |
| |
| glLinkProgram(mProgram); |
| |
| GLint linked = GL_FALSE; |
| glGetProgramiv(mProgram, GL_LINK_STATUS, &linked); |
| ASSERT_GL_TRUE(linked); |
| glUseProgram(mProgram); |
| glUniform4f(location, 0.0, 1.0, 0.0, 1.0); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| class BindUniformLocationES31Test : public BindUniformLocationTest |
| { |
| protected: |
| BindUniformLocationES31Test() : BindUniformLocationTest() {} |
| |
| void linkProgramWithUniformLocation(GLuint vs, |
| GLuint fs, |
| const char *uniformName, |
| GLint uniformLocation) |
| { |
| mProgram = glCreateProgram(); |
| mBindUniformLocation(mProgram, uniformLocation, uniformName); |
| |
| glAttachShader(mProgram, vs); |
| glDeleteShader(vs); |
| glAttachShader(mProgram, fs); |
| glDeleteShader(fs); |
| |
| glLinkProgram(mProgram); |
| } |
| }; |
| |
| // Test for when the shader specifies an explicit uniform location with a layout qualifier and the |
| // bindUniformLocation API sets a consistent location. |
| TEST_P(BindUniformLocationES31Test, ConsistentWithLocationLayoutQualifier) |
| { |
| if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location")) |
| { |
| std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available." |
| << std::endl; |
| return; |
| } |
| |
| const std::string vsSource = |
| "#version 310 es\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(0);\n" |
| "}\n"; |
| |
| const std::string fsSource = |
| "#version 310 es\n" |
| "uniform layout(location=2) highp sampler2D tex;\n" |
| "out highp vec4 my_FragColor;\n" |
| "void main()\n" |
| "{\n" |
| " my_FragColor = texture(tex, vec2(1));\n" |
| "}\n"; |
| |
| const GLuint texLocation = 2; |
| |
| GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource); |
| EXPECT_NE(0u, vs); |
| GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource); |
| EXPECT_NE(0u, fs); |
| linkProgramWithUniformLocation(vs, fs, "tex", texLocation); |
| |
| GLint linked = GL_FALSE; |
| glGetProgramiv(mProgram, GL_LINK_STATUS, &linked); |
| ASSERT_GL_TRUE(linked); |
| |
| EXPECT_EQ(static_cast<GLint>(texLocation), glGetUniformLocation(mProgram, "tex")); |
| glUseProgram(mProgram); |
| glUniform1i(texLocation, 0); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| // Test for when the shader specifies an explicit uniform location with a layout qualifier and the |
| // bindUniformLocation API sets a conflicting location for the same variable. The shader-set |
| // location should prevail. |
| TEST_P(BindUniformLocationES31Test, LocationLayoutQualifierOverridesAPIBinding) |
| { |
| if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location")) |
| { |
| std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available." |
| << std::endl; |
| return; |
| } |
| |
| const std::string vsSource = |
| "#version 310 es\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(0);\n" |
| "}\n"; |
| |
| const std::string fsSource = |
| "#version 310 es\n" |
| "uniform layout(location=2) highp sampler2D tex;\n" |
| "out highp vec4 my_FragColor;\n" |
| "void main()\n" |
| "{\n" |
| " my_FragColor = texture(tex, vec2(1));\n" |
| "}\n"; |
| |
| const GLuint shaderTexLocation = 2; |
| const GLuint texLocation = 3; |
| |
| GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource); |
| EXPECT_NE(0u, vs); |
| GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource); |
| EXPECT_NE(0u, fs); |
| linkProgramWithUniformLocation(vs, fs, "tex", texLocation); |
| |
| GLint linked = GL_FALSE; |
| glGetProgramiv(mProgram, GL_LINK_STATUS, &linked); |
| ASSERT_GL_TRUE(linked); |
| |
| EXPECT_EQ(static_cast<GLint>(shaderTexLocation), glGetUniformLocation(mProgram, "tex")); |
| glUseProgram(mProgram); |
| glUniform1i(shaderTexLocation, 1); |
| EXPECT_GL_NO_ERROR(); |
| glUniform1i(texLocation, 2); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| // Test for when the shader specifies an explicit uniform location with a layout qualifier and the |
| // bindUniformLocation API sets a conflicting location for a different variable. Linking should |
| // fail. |
| TEST_P(BindUniformLocationES31Test, LocationLayoutQualifierConflictsWithAPIBinding) |
| { |
| if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location")) |
| { |
| std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available." |
| << std::endl; |
| return; |
| } |
| |
| const std::string vsSource = |
| "#version 310 es\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(0);\n" |
| "}\n"; |
| |
| const std::string fsSource = |
| "#version 310 es\n" |
| "uniform layout(location=2) highp sampler2D tex;\n" |
| "uniform highp sampler2D tex2;\n" |
| "out highp vec4 my_FragColor;\n" |
| "void main()\n" |
| "{\n" |
| " my_FragColor = texture(tex2, vec2(1));\n" |
| "}\n"; |
| |
| const GLuint tex2Location = 2; |
| |
| GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource); |
| EXPECT_NE(0u, vs); |
| GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource); |
| EXPECT_NE(0u, fs); |
| linkProgramWithUniformLocation(vs, fs, "tex2", tex2Location); |
| |
| GLint linked = GL_FALSE; |
| glGetProgramiv(mProgram, GL_LINK_STATUS, &linked); |
| ASSERT_GL_FALSE(linked); |
| } |
| |
| // 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()); |
| |
| ANGLE_INSTANTIATE_TEST(BindUniformLocationES31Test, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES()) |
| |
| } // namespace |