Path: blob/main_old/src/tests/gl_tests/BindUniformLocationTest.cpp
1693 views
//1// Copyright 2015 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//56// BindUniformLocationTest.cpp : Tests of the GL_CHROMIUM_bind_uniform_location extension.78#include "test_utils/ANGLETest.h"9#include "test_utils/gl_raii.h"1011#include <cmath>1213using namespace angle;1415namespace16{1718class BindUniformLocationTest : public ANGLETest19{20protected:21BindUniformLocationTest()22{23setWindowWidth(128);24setWindowHeight(128);25setConfigRedBits(8);26setConfigGreenBits(8);27setConfigBlueBits(8);28setConfigAlphaBits(8);29}3031void testTearDown() override32{33if (mProgram != 0)34{35glDeleteProgram(mProgram);36}37}3839GLuint mProgram = 0;40};4142// Test basic functionality of GL_CHROMIUM_bind_uniform_location43TEST_P(BindUniformLocationTest, Basic)44{45ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));4647constexpr char kFS[] = R"(precision mediump float;48uniform vec4 u_colorC;49uniform vec4 u_colorB[2];50uniform vec4 u_colorA;51void main()52{53gl_FragColor = u_colorA + u_colorB[0] + u_colorB[1] + u_colorC;54})";5556GLint colorALocation = 3;57GLint colorBLocation = 10;58GLint colorCLocation = 5;5960mProgram = CompileProgram(essl1_shaders::vs::Simple(), kFS, [&](GLuint program) {61glBindUniformLocationCHROMIUM(program, colorALocation, "u_colorA");62glBindUniformLocationCHROMIUM(program, colorBLocation, "u_colorB[0]");63glBindUniformLocationCHROMIUM(program, colorCLocation, "u_colorC");64});65ASSERT_NE(0u, mProgram);6667glUseProgram(mProgram);6869static const float colorB[] = {700.0f, 0.50f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.0f,71};7273glUniform4f(colorALocation, 0.25f, 0.0f, 0.0f, 0.0f);74glUniform4fv(colorBLocation, 2, colorB);75glUniform4f(colorCLocation, 0.0f, 0.0f, 0.0f, 1.0f);7677drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);7879EXPECT_GL_NO_ERROR();80EXPECT_PIXEL_NEAR(0, 0, 64, 128, 192, 255, 1.0);81}8283// Force a sampler location and make sure it samples the correct texture84TEST_P(BindUniformLocationTest, SamplerLocation)85{86ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));8788constexpr char kFS[] = R"(precision mediump float;89uniform vec4 u_colorA;90uniform vec4 u_colorB[2];91uniform sampler2D u_sampler;92void main()93{94gl_FragColor = u_colorA + u_colorB[0] + u_colorB[1] + texture2D(u_sampler, vec2(0, 0));95})";9697GLint colorALocation = 3;98GLint colorBLocation = 10;99GLint samplerLocation = 1;100101mProgram = CompileProgram(essl1_shaders::vs::Simple(), kFS, [&](GLuint program) {102glBindUniformLocationCHROMIUM(program, colorALocation, "u_colorA");103glBindUniformLocationCHROMIUM(program, colorBLocation, "u_colorB[0]");104glBindUniformLocationCHROMIUM(program, samplerLocation, "u_sampler");105});106ASSERT_NE(0u, mProgram);107108glUseProgram(mProgram);109110static const float colorB[] = {1110.0f, 0.50f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.0f,112};113114glUniform4f(colorALocation, 0.25f, 0.0f, 0.0f, 0.0f);115glUniform4fv(colorBLocation, 2, colorB);116117// Point the texture at texture unit 2118glUniform1i(samplerLocation, 2);119120GLTexture texture;121glActiveTexture(GL_TEXTURE2);122glBindTexture(GL_TEXTURE_2D, texture);123constexpr GLubyte kTextureData[] = {32, 32, 32, 255};124glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kTextureData);125126drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);127128EXPECT_GL_NO_ERROR();129EXPECT_PIXEL_NEAR(0, 0, 96, 160, 224, 255, 1.0);130}131132// Test that conflicts are detected when two uniforms are bound to the same location133TEST_P(BindUniformLocationTest, ConflictsDetection)134{135ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));136137constexpr char kFS[] =138R"(precision mediump float;139uniform vec4 u_colorA;140uniform vec4 u_colorB;141void main()142{143gl_FragColor = u_colorA + u_colorB;144})";145146GLint colorALocation = 3;147GLint colorBLocation = 4;148149GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());150GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);151152mProgram = glCreateProgram();153glAttachShader(mProgram, vs);154glDeleteShader(vs);155glAttachShader(mProgram, fs);156glDeleteShader(fs);157158glBindUniformLocationCHROMIUM(mProgram, colorALocation, "u_colorA");159// Bind u_colorB to location a, causing conflicts, link should fail.160glBindUniformLocationCHROMIUM(mProgram, colorALocation, "u_colorB");161glLinkProgram(mProgram);162GLint linked = 0;163glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);164ASSERT_EQ(0, linked);165166// Bind u_colorB to location b, no conflicts, link should succeed.167glBindUniformLocationCHROMIUM(mProgram, colorBLocation, "u_colorB");168glLinkProgram(mProgram);169linked = 0;170glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);171EXPECT_EQ(1, linked);172}173174// Test a use case of the chromium compositor175TEST_P(BindUniformLocationTest, Compositor)176{177ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));178179constexpr char kVS[] =180R"(attribute vec4 a_position;181attribute vec2 a_texCoord;182uniform mat4 matrix;183uniform vec2 color_a[4];184uniform vec4 color_b;185varying vec4 v_color;186void main()187{188v_color.xy = color_a[0] + color_a[1];189v_color.zw = color_a[2] + color_a[3];190v_color += color_b;191gl_Position = matrix * a_position;192})";193194constexpr char kFS[] =195R"(precision mediump float;196varying vec4 v_color;197uniform float alpha;198uniform vec4 multiplier;199uniform vec3 color_c[8];200void main()201{202vec4 color_c_sum = vec4(0.0);203color_c_sum.xyz += color_c[0];204color_c_sum.xyz += color_c[1];205color_c_sum.xyz += color_c[2];206color_c_sum.xyz += color_c[3];207color_c_sum.xyz += color_c[4];208color_c_sum.xyz += color_c[5];209color_c_sum.xyz += color_c[6];210color_c_sum.xyz += color_c[7];211color_c_sum.w = alpha;212color_c_sum *= multiplier;213gl_FragColor = v_color + color_c_sum;214})";215216int counter = 6;217int matrixLocation = counter++;218int colorALocation = counter++;219int colorBLocation = counter++;220int alphaLocation = counter++;221int multiplierLocation = counter++;222int colorCLocation = counter++;223224mProgram = CompileProgram(kVS, kFS, [&](GLuint program) {225glBindUniformLocationCHROMIUM(program, matrixLocation, "matrix");226glBindUniformLocationCHROMIUM(program, colorALocation, "color_a");227glBindUniformLocationCHROMIUM(program, colorBLocation, "color_b");228glBindUniformLocationCHROMIUM(program, alphaLocation, "alpha");229glBindUniformLocationCHROMIUM(program, multiplierLocation, "multiplier");230glBindUniformLocationCHROMIUM(program, colorCLocation, "color_c");231});232ASSERT_NE(0u, mProgram);233234glUseProgram(mProgram);235236static const float colorA[] = {2370.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,238};239240static const float colorC[] = {2410.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,2420.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,243};244245static const float identity[] = {2461, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,247};248249glUniformMatrix4fv(matrixLocation, 1, false, identity);250glUniform2fv(colorALocation, 4, colorA);251glUniform4f(colorBLocation, 0.2f, 0.2f, 0.2f, 0.2f);252glUniform1f(alphaLocation, 0.8f);253glUniform4f(multiplierLocation, 0.5f, 0.5f, 0.5f, 0.5f);254glUniform3fv(colorCLocation, 8, colorC);255256glDrawArrays(GL_TRIANGLES, 0, 6);257258drawQuad(mProgram, "a_position", 0.5f);259260EXPECT_PIXEL_EQ(0, 0, 204, 204, 204, 204);261}262263// Test that unused uniforms don't conflict when bound to the same location264TEST_P(BindUniformLocationTest, UnusedUniformUpdate)265{266ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));267268ASSERT_NE(nullptr, glBindUniformLocationCHROMIUM);269270constexpr char kFS[] = R"(precision mediump float;271uniform vec4 u_colorA;272uniform float u_colorU;273uniform vec4 u_colorC;274void main()275{276gl_FragColor = u_colorA + u_colorC;277})";278279const GLint colorULocation = 1;280const GLint nonexistingLocation = 5;281const GLint unboundLocation = 6;282283mProgram = CompileProgram(essl1_shaders::vs::Simple(), kFS, [&](GLuint program) {284glBindUniformLocationCHROMIUM(program, colorULocation, "u_colorU");285// The non-existing uniform should behave like existing, but optimized away286// uniform.287glBindUniformLocationCHROMIUM(program, nonexistingLocation, "nonexisting");288// Let A and C be assigned automatic locations.289});290ASSERT_NE(0u, mProgram);291292glUseProgram(mProgram);293294// No errors on bound locations, since caller does not know295// if the driver optimizes them away or not.296glUniform1f(colorULocation, 0.25f);297EXPECT_GL_NO_ERROR();298299// No errors on bound locations of names that do not exist300// in the shader. Otherwise it would be inconsistent wrt the301// optimization case.302glUniform1f(nonexistingLocation, 0.25f);303EXPECT_GL_NO_ERROR();304305// The above are equal to updating -1.306glUniform1f(-1, 0.25f);307EXPECT_GL_NO_ERROR();308309// No errors when updating with other type either.310// The type can not be known with the non-existing case.311glUniform2f(colorULocation, 0.25f, 0.25f);312EXPECT_GL_NO_ERROR();313glUniform2f(nonexistingLocation, 0.25f, 0.25f);314EXPECT_GL_NO_ERROR();315glUniform2f(-1, 0.25f, 0.25f);316EXPECT_GL_NO_ERROR();317318// Ensure that driver or ANGLE has optimized the variable319// away and the test tests what it is supposed to.320EXPECT_EQ(-1, glGetUniformLocation(mProgram, "u_colorU"));321322// The bound location gets marked as used and the driver323// does not allocate other variables to that location.324EXPECT_NE(colorULocation, glGetUniformLocation(mProgram, "u_colorA"));325EXPECT_NE(colorULocation, glGetUniformLocation(mProgram, "u_colorC"));326EXPECT_NE(nonexistingLocation, glGetUniformLocation(mProgram, "u_colorA"));327EXPECT_NE(nonexistingLocation, glGetUniformLocation(mProgram, "u_colorC"));328329// Unintuitive: while specifying value works, getting the value does not.330GLfloat getResult = 0.0f;331glGetUniformfv(mProgram, colorULocation, &getResult);332EXPECT_GL_ERROR(GL_INVALID_OPERATION);333glGetUniformfv(mProgram, nonexistingLocation, &getResult);334EXPECT_GL_ERROR(GL_INVALID_OPERATION);335glGetUniformfv(mProgram, -1, &getResult);336EXPECT_GL_ERROR(GL_INVALID_OPERATION);337338// Updating an unbound, non-existing location still causes339// an error.340glUniform1f(unboundLocation, 0.25f);341EXPECT_GL_ERROR(GL_INVALID_OPERATION);342}343344// GL backend optimizes away a uniform in the vertex shader if it's only used to345// compute a varying that is never referenced in the fragment shader.346TEST_P(BindUniformLocationTest, UnusedUniformUpdateComplex)347{348ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));349350ASSERT_NE(nullptr, glBindUniformLocationCHROMIUM);351352constexpr char kVS[] = R"(precision highp float;353attribute vec4 a_position;354varying vec4 v_unused;355uniform vec4 u_unused;356void main()357{358gl_Position = a_position;359v_unused = u_unused;360}361)";362363constexpr char kFS[] = R"(precision mediump float;364varying vec4 v_unused;365void main()366{367gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);368})";369370const GLint unusedLocation = 1;371372mProgram = CompileProgram(kVS, kFS, [&](GLuint program) {373glBindUniformLocationCHROMIUM(program, unusedLocation, "u_unused");374});375ASSERT_NE(0u, mProgram);376377glUseProgram(mProgram);378379// No errors on bound locations of names that do not exist380// in the shader. Otherwise it would be inconsistent wrt the381// optimization case.382glUniform4f(unusedLocation, 0.25f, 0.25f, 0.25f, 0.25f);383EXPECT_GL_NO_ERROR();384}385386// Test for a bug where using a sampler caused GL error if the mProgram had387// uniforms that were optimized away by the driver. This was only a problem with388// glBindUniformLocationCHROMIUM implementation. This could be reproed by389// binding the sampler to a location higher than the amount of active uniforms.390TEST_P(BindUniformLocationTest, UseSamplerWhenUnusedUniforms)391{392ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));393394constexpr char kFS[] =395R"(uniform sampler2D tex;396void main()397{398gl_FragColor = texture2D(tex, vec2(1));399})";400401const GLuint texLocation = 54;402403mProgram = CompileProgram(essl1_shaders::vs::Simple(), kFS, [&](GLuint program) {404glBindUniformLocationCHROMIUM(program, texLocation, "tex");405});406ASSERT_NE(0u, mProgram);407408glUseProgram(mProgram);409glUniform1i(texLocation, 0);410EXPECT_GL_NO_ERROR();411}412413// Test for binding a statically used uniform to the same location as a non-statically used uniform.414// This is valid according to the extension spec.415TEST_P(BindUniformLocationTest, SameLocationForUsedAndUnusedUniform)416{417ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));418419constexpr char kFS[] =420R"(precision mediump float;421uniform vec4 a;422uniform vec4 b;423void main()424{425gl_FragColor = a;426})";427428const GLuint location = 54;429430mProgram = CompileProgram(essl1_shaders::vs::Zero(), kFS, [&](GLuint program) {431glBindUniformLocationCHROMIUM(program, location, "a");432glBindUniformLocationCHROMIUM(program, location, "b");433});434ASSERT_NE(0u, mProgram);435436glUseProgram(mProgram);437glUniform4f(location, 0.0, 1.0, 0.0, 1.0);438EXPECT_GL_NO_ERROR();439}440441class BindUniformLocationES31Test : public BindUniformLocationTest442{443protected:444BindUniformLocationES31Test() : BindUniformLocationTest() {}445446void linkProgramWithUniformLocation(const char *vs,447const char *fs,448const char *uniformName,449GLint uniformLocation)450{451mProgram = CompileProgram(vs, fs, [&](GLuint program) {452glBindUniformLocationCHROMIUM(program, uniformLocation, uniformName);453});454}455};456457// Test for when the shader specifies an explicit uniform location with a layout qualifier and the458// bindUniformLocation API sets a consistent location.459TEST_P(BindUniformLocationES31Test, ConsistentWithLocationLayoutQualifier)460{461ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));462463constexpr char kFS[] =464"#version 310 es\n"465"uniform layout(location=2) highp sampler2D tex;\n"466"out highp vec4 my_FragColor;\n"467"void main()\n"468"{\n"469" my_FragColor = texture(tex, vec2(1));\n"470"}\n";471472const GLuint texLocation = 2;473474linkProgramWithUniformLocation(essl31_shaders::vs::Zero(), kFS, "tex", texLocation);475476GLint linked = GL_FALSE;477glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);478ASSERT_GL_TRUE(linked);479480EXPECT_EQ(static_cast<GLint>(texLocation), glGetUniformLocation(mProgram, "tex"));481glUseProgram(mProgram);482glUniform1i(texLocation, 0);483EXPECT_GL_NO_ERROR();484}485486// Test for when the shader specifies an explicit uniform location with a layout qualifier and the487// bindUniformLocation API sets a conflicting location for the same variable. The shader-set488// location should prevail.489TEST_P(BindUniformLocationES31Test, LocationLayoutQualifierOverridesAPIBinding)490{491ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));492493constexpr char kFS[] =494"#version 310 es\n"495"uniform layout(location=2) highp sampler2D tex;\n"496"out highp vec4 my_FragColor;\n"497"void main()\n"498"{\n"499" my_FragColor = texture(tex, vec2(1));\n"500"}\n";501502const GLuint shaderTexLocation = 2;503const GLuint texLocation = 3;504505linkProgramWithUniformLocation(essl31_shaders::vs::Zero(), kFS, "tex", texLocation);506507GLint linked = GL_FALSE;508glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);509ASSERT_GL_TRUE(linked);510511EXPECT_EQ(static_cast<GLint>(shaderTexLocation), glGetUniformLocation(mProgram, "tex"));512glUseProgram(mProgram);513glUniform1i(shaderTexLocation, 1);514EXPECT_GL_NO_ERROR();515glUniform1i(texLocation, 2);516EXPECT_GL_NO_ERROR();517}518519// Test for when the shader specifies an explicit uniform location with a layout qualifier and the520// bindUniformLocation API sets a conflicting location for a different variable. Linking should521// fail.522TEST_P(BindUniformLocationES31Test, LocationLayoutQualifierConflictsWithAPIBinding)523{524ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));525526constexpr char kFS[] =527"#version 310 es\n"528"uniform layout(location=2) highp sampler2D tex;\n"529"uniform highp sampler2D tex2;\n"530"out highp vec4 my_FragColor;\n"531"void main()\n"532"{\n"533" my_FragColor = texture(tex2, vec2(1));\n"534"}\n";535536const GLuint tex2Location = 2;537538linkProgramWithUniformLocation(essl31_shaders::vs::Zero(), kFS, "tex2", tex2Location);539540GLint linked = GL_FALSE;541glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);542ASSERT_GL_FALSE(linked);543}544545// Test for binding a location for an array of arrays uniform.546TEST_P(BindUniformLocationES31Test, ArrayOfArrays)547{548ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_bind_uniform_location"));549550constexpr char kFS[] =551R"(#version 310 es552precision highp float;553uniform vec4 sourceColor[2][1];554out highp vec4 my_FragColor;555void main()556{557my_FragColor = sourceColor[1][0];558})";559560const GLuint location = 8;561562linkProgramWithUniformLocation(essl31_shaders::vs::Simple(), kFS, "sourceColor[1]", location);563564GLint linked = GL_FALSE;565glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);566ASSERT_GL_TRUE(linked);567568glUseProgram(mProgram);569glUniform4f(location, 0.0f, 1.0f, 0.0f, 1.0f);570571drawQuad(mProgram, essl31_shaders::PositionAttrib(), 0.5f);572EXPECT_GL_NO_ERROR();573574EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);575}576577// Use this to select which configurations (e.g. which renderer, which GLES major version) these578// tests should be run against.579ANGLE_INSTANTIATE_TEST_ES2(BindUniformLocationTest);580581GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BindUniformLocationES31Test);582ANGLE_INSTANTIATE_TEST_ES31(BindUniformLocationES31Test);583584} // namespace585586587