| // |
| // Copyright 2017 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. |
| // |
| |
| // ProgramInterfaceTest: Tests of program interfaces. |
| |
| #include "common/string_utils.h" |
| #include "test_utils/ANGLETest.h" |
| #include "test_utils/gl_raii.h" |
| |
| using namespace angle; |
| |
| namespace |
| { |
| |
| class ProgramInterfaceTestES31 : public ANGLETest |
| { |
| protected: |
| ProgramInterfaceTestES31() |
| { |
| setWindowWidth(64); |
| setWindowHeight(64); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| }; |
| |
| // Tests glGetProgramResourceIndex. |
| TEST_P(ProgramInterfaceTestES31, GetResourceIndex) |
| { |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "uniform vec4 color;\n" |
| "out vec4 oColor;\n" |
| "void main()\n" |
| "{\n" |
| " oColor = color;\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); |
| |
| GLuint index = |
| glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, essl31_shaders::PositionAttrib()); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "missing"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(GL_INVALID_INDEX, index); |
| |
| index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "missing"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(GL_INVALID_INDEX, index); |
| |
| index = glGetProgramResourceIndex(program, GL_ATOMIC_COUNTER_BUFFER, "missing"); |
| EXPECT_GL_ERROR(GL_INVALID_ENUM); |
| } |
| |
| // Tests glGetProgramResourceName. |
| TEST_P(ProgramInterfaceTestES31, GetResourceName) |
| { |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "uniform vec4 color;\n" |
| "out vec4 oColor[4];\n" |
| "void main()\n" |
| "{\n" |
| " oColor[0] = color;\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); |
| |
| GLuint index = |
| glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, essl31_shaders::PositionAttrib()); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLchar name[64]; |
| GLsizei length; |
| glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(static_cast<int>(strlen(essl31_shaders::PositionAttrib())), length); |
| EXPECT_EQ(essl31_shaders::PositionAttrib(), std::string(name)); |
| |
| glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, 4, &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(3, length); |
| EXPECT_TRUE(angle::BeginsWith(essl31_shaders::PositionAttrib(), name)); |
| |
| glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, -1, &length, name); |
| EXPECT_GL_ERROR(GL_INVALID_VALUE); |
| |
| glGetProgramResourceName(program, GL_PROGRAM_INPUT, GL_INVALID_INDEX, sizeof(name), &length, |
| name); |
| EXPECT_GL_ERROR(GL_INVALID_VALUE); |
| |
| index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(9, length); |
| EXPECT_EQ("oColor[0]", std::string(name)); |
| |
| glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, 8, &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(7, length); |
| EXPECT_EQ("oColor[", std::string(name)); |
| } |
| |
| // Tests glGetProgramResourceLocation. |
| TEST_P(ProgramInterfaceTestES31, GetResourceLocation) |
| { |
| // http://anglebug.com/4092 |
| ANGLE_SKIP_TEST_IF(isSwiftshader()); |
| constexpr char kVS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "layout(location = 3) in highp vec4 position;\n" |
| "in highp vec4 noLocationSpecified;\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = position;\n" |
| "}"; |
| |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "uniform vec4 color;\n" |
| "layout(location = 2) out vec4 oColor[4];\n" |
| "void main()\n" |
| "{\n" |
| " oColor[0] = color;\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, kVS, kFS); |
| |
| GLenum invalidInterfaces[] = {GL_UNIFORM_BLOCK, GL_TRANSFORM_FEEDBACK_VARYING, |
| GL_BUFFER_VARIABLE, GL_SHADER_STORAGE_BLOCK, |
| GL_ATOMIC_COUNTER_BUFFER}; |
| GLint location; |
| for (auto &invalidInterface : invalidInterfaces) |
| { |
| location = glGetProgramResourceLocation(program, invalidInterface, "any"); |
| EXPECT_GL_ERROR(GL_INVALID_ENUM); |
| EXPECT_EQ(-1, location); |
| } |
| |
| location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(3, location); |
| |
| location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "noLocationSpecified"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(-1, location); |
| |
| location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "missing"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(-1, location); |
| |
| location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(2, location); |
| location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor[0]"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(2, location); |
| location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor[3]"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(5, location); |
| } |
| |
| // Tests glGetProgramResource. |
| TEST_P(ProgramInterfaceTestES31, GetResource) |
| { |
| // http://anglebug.com/4092 |
| ANGLE_SKIP_TEST_IF(isSwiftshader()); |
| constexpr char kVS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "layout(location = 3) in highp vec4 position;\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = position;\n" |
| "}"; |
| |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "uniform vec4 color;\n" |
| "layout(location = 2) out vec4 oColor[4];\n" |
| "void main()\n" |
| "{\n" |
| " oColor[0] = color;\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, kVS, kFS); |
| |
| GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLenum props[] = {GL_TYPE, |
| GL_ARRAY_SIZE, |
| GL_LOCATION, |
| GL_NAME_LENGTH, |
| GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, |
| GL_REFERENCED_BY_COMPUTE_SHADER}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| GLint params[ArraySize(props)]; |
| GLsizei length; |
| |
| glGetProgramResourceiv(program, GL_PROGRAM_INPUT, index, propCount, props, propCount, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(GL_FLOAT_VEC4, params[0]); // type |
| EXPECT_EQ(1, params[1]); // array_size |
| EXPECT_EQ(3, params[2]); // location |
| EXPECT_EQ(9, params[3]); // name_length |
| EXPECT_EQ(1, params[4]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[5]); // referenced_by_fragment_shader |
| EXPECT_EQ(0, params[6]); // referenced_by_compute_shader |
| |
| index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor[0]"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(index, GL_INVALID_INDEX); |
| // bufSize is smaller than propCount. |
| glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, propCount, props, propCount - 1, |
| &length, params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount - 1, length); |
| EXPECT_EQ(GL_FLOAT_VEC4, params[0]); // type |
| EXPECT_EQ(4, params[1]); // array_size |
| EXPECT_EQ(2, params[2]); // location |
| EXPECT_EQ(10, params[3]); // name_length |
| EXPECT_EQ(0, params[4]); // referenced_by_vertex_shader |
| EXPECT_EQ(1, params[5]); // referenced_by_fragment_shader |
| |
| GLenum invalidOutputProp = GL_OFFSET; |
| glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, 1, &invalidOutputProp, 1, &length, |
| params); |
| EXPECT_GL_ERROR(GL_INVALID_OPERATION); |
| } |
| |
| // Tests glGetProgramInterfaceiv. |
| TEST_P(ProgramInterfaceTestES31, GetProgramInterface) |
| { |
| // TODO(jiajia.qin@intel.com): Don't skip this test once SSBO are supported on render pipeline. |
| // http://anglebug.com/1951 |
| ANGLE_SKIP_TEST_IF(IsD3D11()); |
| |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "uniform vec4 color;\n" |
| "out vec4 oColor;\n" |
| "uniform ub {\n" |
| " vec4 mem0;\n" |
| " vec4 mem1;\n" |
| "} instance;\n" |
| "layout(std430) buffer shaderStorageBlock1 {\n" |
| " vec3 target;\n" |
| "};\n" |
| "layout(std430) buffer shaderStorageBlock2 {\n" |
| " vec3 target;\n" |
| "} blockInstance2[1];\n" |
| "void main()\n" |
| "{\n" |
| " oColor = color;\n" |
| " target = vec3(0, 0, 0);\n" |
| " blockInstance2[0].target = vec3(1, 1, 1);\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS); |
| |
| GLint num; |
| glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(1, num); |
| |
| glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(static_cast<GLint>(strlen(essl3_shaders::PositionAttrib())) + 1, num); |
| |
| glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &num); |
| EXPECT_GL_ERROR(GL_INVALID_OPERATION); |
| |
| glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(1, num); |
| |
| glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(7, num); |
| |
| glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &num); |
| EXPECT_GL_ERROR(GL_INVALID_OPERATION); |
| |
| glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(1, num); |
| |
| glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NAME_LENGTH, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(3, num); |
| |
| glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(2, num); // mem0, mem1 |
| |
| glGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(3, num); |
| |
| glGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(8, num); // "ub.mem0" |
| |
| glGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NUM_ACTIVE_VARIABLES, &num); |
| EXPECT_GL_ERROR(GL_INVALID_OPERATION); |
| |
| glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(2, num); |
| |
| glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(23, num); // "shaderStorageBlock2[0]" |
| |
| glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(1, num); |
| } |
| |
| // Tests the resource property query for uniform can be done correctly. |
| TEST_P(ProgramInterfaceTestES31, GetUniformProperties) |
| { |
| // TODO(jiajia.qin@intel.com): Don't skip this test once atomic counter is supported on d3d |
| // backend. http://anglebug.com/1729 |
| ANGLE_SKIP_TEST_IF(IsD3D11()); |
| |
| constexpr char kVS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "uniform layout(location=12) vec4 color;\n" |
| "layout(binding = 2, offset = 4) uniform atomic_uint foo;\n" |
| "void main()\n" |
| "{\n" |
| " atomicCounterIncrement(foo);\n" |
| "}"; |
| |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "uniform vec4 color;\n" |
| "out vec4 oColor;\n" |
| "void main()\n" |
| "{\n" |
| " oColor = color;\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, kVS, kFS); |
| |
| GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "color"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLchar name[64]; |
| GLsizei length; |
| glGetProgramResourceName(program, GL_UNIFORM, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(5, length); |
| EXPECT_EQ("color", std::string(name)); |
| |
| GLint location = glGetProgramResourceLocation(program, GL_UNIFORM, "color"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(12, location); |
| |
| GLenum props[] = {GL_TYPE, |
| GL_ARRAY_SIZE, |
| GL_LOCATION, |
| GL_NAME_LENGTH, |
| GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, |
| GL_REFERENCED_BY_COMPUTE_SHADER, |
| GL_ARRAY_STRIDE, |
| GL_BLOCK_INDEX, |
| GL_IS_ROW_MAJOR, |
| GL_MATRIX_STRIDE, |
| GL_OFFSET, |
| GL_ATOMIC_COUNTER_BUFFER_INDEX}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| GLint params[ArraySize(props)]; |
| glGetProgramResourceiv(program, GL_UNIFORM, index, propCount, props, propCount, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(GL_FLOAT_VEC4, params[0]); // type |
| EXPECT_EQ(1, params[1]); // array_size |
| EXPECT_EQ(12, params[2]); // location |
| EXPECT_EQ(6, params[3]); // name_length |
| EXPECT_EQ(0, params[4]); // referenced_by_vertex_shader |
| EXPECT_EQ(1, params[5]); // referenced_by_fragment_shader |
| EXPECT_EQ(0, params[6]); // referenced_by_compute_shader |
| EXPECT_EQ(-1, params[7]); // array_stride |
| EXPECT_EQ(-1, params[8]); // block_index |
| EXPECT_EQ(0, params[9]); // is_row_major |
| EXPECT_EQ(-1, params[10]); // matrix_stride |
| EXPECT_EQ(-1, params[11]); // offset |
| EXPECT_EQ(-1, params[12]); // atomic_counter_buffer_index |
| |
| index = glGetProgramResourceIndex(program, GL_UNIFORM, "foo"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| glGetProgramResourceName(program, GL_UNIFORM, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(3, length); |
| EXPECT_EQ("foo", std::string(name)); |
| |
| location = glGetProgramResourceLocation(program, GL_UNIFORM, "foo"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(-1, location); |
| |
| glGetProgramResourceiv(program, GL_UNIFORM, index, propCount, props, propCount, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(GL_UNSIGNED_INT_ATOMIC_COUNTER, params[0]); // type |
| EXPECT_EQ(1, params[1]); // array_size |
| EXPECT_EQ(-1, params[2]); // location |
| EXPECT_EQ(4, params[3]); // name_length |
| EXPECT_EQ(1, params[4]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[5]); // referenced_by_fragment_shader |
| EXPECT_EQ(0, params[6]); // referenced_by_compute_shader |
| EXPECT_EQ(0, params[7]); // array_stride |
| EXPECT_EQ(-1, params[8]); // block_index |
| EXPECT_EQ(0, params[9]); // is_row_major |
| EXPECT_EQ(0, params[10]); // matrix_stride |
| EXPECT_EQ(4, params[11]); // offset |
| EXPECT_NE(-1, params[12]); // atomic_counter_buffer_index |
| } |
| |
| // Tests the resource property query for uniform block can be done correctly. |
| TEST_P(ProgramInterfaceTestES31, GetUniformBlockProperties) |
| { |
| constexpr char kVS[] = |
| "#version 310 es\n" |
| "in vec2 position;\n" |
| "out vec2 v;\n" |
| "layout(binding = 2) uniform blockName {\n" |
| " float f1;\n" |
| " float f2;\n" |
| "} instanceName;\n" |
| "void main() {\n" |
| " v = vec2(instanceName.f1, instanceName.f2);\n" |
| " gl_Position = vec4(position, 0, 1);\n" |
| "}"; |
| |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "in vec2 v;\n" |
| "out vec4 color;\n" |
| "void main() {\n" |
| " color = vec4(v, 0, 1);\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, kVS, kFS); |
| |
| GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "blockName"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLchar name[64]; |
| GLsizei length; |
| glGetProgramResourceName(program, GL_UNIFORM_BLOCK, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(9, length); |
| EXPECT_EQ("blockName", std::string(name)); |
| |
| GLenum props[] = {GL_BUFFER_BINDING, |
| GL_BUFFER_DATA_SIZE, |
| GL_NAME_LENGTH, |
| GL_NUM_ACTIVE_VARIABLES, |
| GL_ACTIVE_VARIABLES, |
| GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, |
| GL_REFERENCED_BY_COMPUTE_SHADER}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| constexpr int kBufSize = 256; |
| GLint params[kBufSize]; |
| GLint magic = 0xBEEF; |
| |
| // Tests bufSize is respected even some prop returns more than one value. |
| params[propCount] = magic; |
| glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, propCount, props, propCount, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(2, params[0]); // buffer_binding |
| EXPECT_NE(0, params[1]); // buffer_data_size |
| EXPECT_EQ(10, params[2]); // name_length |
| EXPECT_EQ(2, params[3]); // num_active_variables |
| EXPECT_LE(0, params[4]); // index of 'f1' or 'f2' |
| EXPECT_LE(0, params[5]); // index of 'f1' or 'f2' |
| EXPECT_EQ(1, params[6]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[7]); // referenced_by_fragment_shader |
| EXPECT_EQ(magic, params[8]); |
| |
| glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, propCount, props, kBufSize, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount + 1, length); |
| EXPECT_EQ(0, params[8]); // referenced_by_compute_shader |
| |
| // bufSize is reached in middle of outputting values for GL_ACTIVE_VARIABLES. |
| GLenum actvieVariablesProperty = GL_ACTIVE_VARIABLES; |
| params[1] = magic; |
| glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, 1, &actvieVariablesProperty, 1, |
| &length, params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(1, length); |
| EXPECT_LE(0, params[0]); // index of 'f1' or 'f2' |
| EXPECT_EQ(magic, params[1]); |
| } |
| |
| // Tests atomic counter buffer qeury works correctly. |
| TEST_P(ProgramInterfaceTestES31, QueryAtomicCounteBuffer) |
| { |
| // TODO(jiajia.qin@intel.com): Don't skip this test once atomic counter is supported on d3d |
| // backend. http://anglebug.com/1729 |
| ANGLE_SKIP_TEST_IF(IsD3D11()); |
| |
| constexpr char kVS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "layout(binding = 2, offset = 0) uniform atomic_uint vcounter;\n" |
| "in highp vec4 a_position;\n" |
| "void main()\n" |
| "{\n" |
| " atomicCounterIncrement(vcounter);\n" |
| " gl_Position = a_position;\n" |
| "}\n"; |
| |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "layout(binding = 2, offset = 4) uniform atomic_uint fcounter;\n" |
| "out highp vec4 my_color;\n" |
| "void main()\n" |
| "{\n" |
| " atomicCounterDecrement(fcounter);\n" |
| " my_color = vec4(0.0);\n" |
| "}\n"; |
| |
| ANGLE_GL_PROGRAM(program, kVS, kFS); |
| GLint num; |
| glGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(1, num); |
| |
| glGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(2, num); |
| |
| GLenum props[] = {GL_BUFFER_BINDING, GL_NUM_ACTIVE_VARIABLES, GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, GL_REFERENCED_BY_COMPUTE_SHADER}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| GLint params[ArraySize(props)]; |
| GLsizei length = 0; |
| glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, 0, propCount, props, propCount, |
| &length, params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(2, params[0]); // buffer_binding |
| EXPECT_EQ(2, params[1]); // num_active_variables |
| EXPECT_EQ(1, params[2]); // referenced_by_vertex_shader |
| EXPECT_EQ(1, params[3]); // referenced_by_fragment_shader |
| EXPECT_EQ(0, params[4]); // referenced_by_compute_shader |
| } |
| |
| // Tests the resource property query for buffer variable can be done correctly. |
| TEST_P(ProgramInterfaceTestES31, GetBufferVariableProperties) |
| { |
| // TODO(jiajia.qin@intel.com): Don't skip this test once non-simple SSBO sentences are supported |
| // on d3d backend. http://anglebug.com/1951 |
| ANGLE_SKIP_TEST_IF(IsD3D11()); |
| |
| constexpr char kVS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "struct S {\n" |
| " vec3 a;\n" |
| " ivec2 b[4];\n" |
| "};\n" |
| "layout(std140) buffer blockName0 {\n" |
| " S s0;\n" |
| " vec2 v0;\n" |
| " S s1[2];\n" |
| " uint u0;\n" |
| "};\n" |
| "layout(binding = 1) buffer blockName1 {\n" |
| " uint u1[2];\n" |
| " float f1;\n" |
| "} instanceName1[2];\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(instanceName1[0].f1, s1[0].a);\n" |
| "}\n"; |
| |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "layout(binding = 1) buffer blockName1 {\n" |
| " uint u1[2];\n" |
| " float f1;\n" |
| "} instanceName1[2];\n" |
| "out vec4 oColor;\n" |
| "void main()\n" |
| "{\n" |
| " oColor = vec4(instanceName1[0].f1, 0, 0, 1);\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, kVS, kFS); |
| |
| GLuint index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockName1.f1"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLchar name[64]; |
| GLsizei length; |
| glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(13, length); |
| EXPECT_EQ("blockName1.f1", std::string(name)); |
| |
| GLenum props[] = {GL_ARRAY_SIZE, |
| GL_ARRAY_STRIDE, |
| GL_BLOCK_INDEX, |
| GL_IS_ROW_MAJOR, |
| GL_MATRIX_STRIDE, |
| GL_NAME_LENGTH, |
| GL_OFFSET, |
| GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, |
| GL_REFERENCED_BY_COMPUTE_SHADER, |
| GL_TOP_LEVEL_ARRAY_SIZE, |
| GL_TOP_LEVEL_ARRAY_STRIDE, |
| GL_TYPE}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| constexpr int kBufSize = 256; |
| GLint params[kBufSize]; |
| |
| glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(1, params[0]); // array_size |
| EXPECT_LE(0, params[1]); // array_stride |
| EXPECT_LE(0, params[2]); // block_index |
| EXPECT_EQ(0, params[3]); // is_row_major |
| EXPECT_EQ(0, params[4]); // matrix_stride |
| EXPECT_EQ(14, params[5]); // name_length |
| EXPECT_LE(0, params[6]); // offset |
| |
| EXPECT_EQ(1, params[7]); // referenced_by_vertex_shader |
| EXPECT_EQ(1, params[8]); // referenced_by_fragment_shader |
| EXPECT_EQ(0, params[9]); // referenced_by_compute_shader |
| |
| EXPECT_EQ(1, params[10]); // top_level_array_size |
| EXPECT_LE(0, params[11]); // top_level_array_stride |
| |
| EXPECT_EQ(GL_FLOAT, params[12]); // type |
| |
| index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "s1[0].a"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(7, length); |
| EXPECT_EQ("s1[0].a", std::string(name)); |
| |
| glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(1, params[0]); // array_size |
| EXPECT_LE(0, params[1]); // array_stride |
| EXPECT_LE(0, params[2]); // block_index |
| EXPECT_EQ(0, params[3]); // is_row_major |
| EXPECT_EQ(0, params[4]); // matrix_stride |
| EXPECT_EQ(8, params[5]); // name_length |
| EXPECT_LE(0, params[6]); // offset |
| |
| EXPECT_EQ(1, params[7]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[8]); // referenced_by_fragment_shader |
| EXPECT_EQ(0, params[9]); // referenced_by_compute_shader |
| |
| EXPECT_EQ(2, params[10]); // top_level_array_size |
| EXPECT_EQ(80, params[11]); // top_level_array_stride |
| |
| EXPECT_EQ(GL_FLOAT_VEC3, params[12]); // type |
| } |
| |
| // Tests the resource property querying for buffer variable in std430 SSBO works correctly. |
| TEST_P(ProgramInterfaceTestES31, GetStd430BufferVariableProperties) |
| { |
| ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL()); |
| |
| constexpr char kComputeShaderSource[] = |
| R"(#version 310 es |
| layout(local_size_x=1, local_size_y=1, local_size_z=1) in; |
| struct S |
| { |
| uvec2 v; |
| mat2 m; |
| }; |
| layout(std430, binding = 0) buffer blockIn { |
| uint u; |
| uint a[2]; |
| S s; |
| } instanceIn; |
| layout(std430, binding = 1) buffer blockOut { |
| uint u; |
| uint a[2]; |
| S s; |
| } instanceOut; |
| void main() |
| { |
| instanceOut.u = instanceIn.u; |
| instanceOut.a[0] = instanceIn.a[0]; |
| instanceOut.a[1] = instanceIn.a[1]; |
| instanceOut.s.v = instanceIn.s.v; |
| instanceOut.s.m = instanceIn.s.m; |
| } |
| )"; |
| |
| ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource); |
| |
| GLuint index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockIn.a"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLchar name[64]; |
| GLsizei length; |
| glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(12, length); |
| EXPECT_EQ("blockIn.a[0]", std::string(name)); |
| |
| GLenum props[] = {GL_ARRAY_SIZE, |
| GL_ARRAY_STRIDE, |
| GL_BLOCK_INDEX, |
| GL_IS_ROW_MAJOR, |
| GL_MATRIX_STRIDE, |
| GL_NAME_LENGTH, |
| GL_OFFSET, |
| GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, |
| GL_REFERENCED_BY_COMPUTE_SHADER, |
| GL_TOP_LEVEL_ARRAY_SIZE, |
| GL_TOP_LEVEL_ARRAY_STRIDE, |
| GL_TYPE}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| constexpr int kBufSize = 256; |
| GLint params[kBufSize]; |
| |
| glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(2, params[0]); // array_size |
| EXPECT_LE(4, params[1]); // array_stride |
| EXPECT_LE(0, params[2]); // block_index |
| EXPECT_EQ(0, params[3]); // is_row_major |
| EXPECT_EQ(0, params[4]); // matrix_stride |
| EXPECT_EQ(13, params[5]); // name_length |
| EXPECT_EQ(4, params[6]); // offset |
| |
| EXPECT_EQ(0, params[7]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[8]); // referenced_by_fragment_shader |
| EXPECT_EQ(1, params[9]); // referenced_by_compute_shader |
| |
| EXPECT_EQ(1, params[10]); // top_level_array_size |
| EXPECT_EQ(0, params[11]); // top_level_array_stride |
| EXPECT_EQ(GL_UNSIGNED_INT, params[12]); // type |
| |
| index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockIn.s.m"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(11, length); |
| EXPECT_EQ("blockIn.s.m", std::string(name)); |
| |
| glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(1, params[0]); // array_size |
| EXPECT_LE(0, params[1]); // array_stride |
| EXPECT_LE(0, params[2]); // block_index |
| EXPECT_EQ(0, params[3]); // is_row_major |
| EXPECT_EQ(8, params[4]); // matrix_stride |
| EXPECT_EQ(12, params[5]); // name_length |
| EXPECT_EQ(24, params[6]); // offset |
| |
| EXPECT_EQ(0, params[7]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[8]); // referenced_by_fragment_shader |
| // TODO(jiajia.qin@intel.com): referenced_by_compute_shader is not |
| // correctly handled. http://anglebug.com/1920. |
| // EXPECT_EQ(1, params[9]); // referenced_by_compute_shader |
| |
| EXPECT_EQ(1, params[10]); // top_level_array_size |
| EXPECT_EQ(0, params[11]); // top_level_array_stride |
| EXPECT_EQ(GL_FLOAT_MAT2, params[12]); // type |
| } |
| |
| // Test that TOP_LEVEL_ARRAY_STRIDE for buffer variable with aggregate type works correctly. |
| TEST_P(ProgramInterfaceTestES31, TopLevelArrayStrideWithAggregateType) |
| { |
| constexpr char kComputeShaderSource[] = |
| R"(#version 310 es |
| layout(local_size_x=1, local_size_y=1, local_size_z=1) in; |
| struct S |
| { |
| uvec2 v; |
| mat2 m; |
| }; |
| layout(std430, binding = 0) buffer blockIn { |
| uint u; |
| uint a[2]; |
| S s; |
| } instanceIn; |
| layout(std430, binding = 1) buffer blockOut { |
| uint u; |
| uint a[4][3]; |
| S s[3][2]; |
| } instanceOut; |
| void main() |
| { |
| instanceOut.u = instanceIn.u; |
| instanceOut.a[0][0] = instanceIn.a[0]; |
| instanceOut.a[0][1] = instanceIn.a[1]; |
| instanceOut.s[0][0].v = instanceIn.s.v; |
| instanceOut.s[0][0].m = instanceIn.s.m; |
| } |
| )"; |
| |
| ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource); |
| |
| GLuint index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockOut.s[0][0].m"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLchar name[64]; |
| GLsizei length; |
| glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(18, length); |
| EXPECT_EQ("blockOut.s[0][0].m", std::string(name)); |
| |
| GLenum props[] = {GL_ARRAY_SIZE, |
| GL_ARRAY_STRIDE, |
| GL_BLOCK_INDEX, |
| GL_IS_ROW_MAJOR, |
| GL_MATRIX_STRIDE, |
| GL_NAME_LENGTH, |
| GL_OFFSET, |
| GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, |
| GL_REFERENCED_BY_COMPUTE_SHADER, |
| GL_TOP_LEVEL_ARRAY_SIZE, |
| GL_TOP_LEVEL_ARRAY_STRIDE, |
| GL_TYPE}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| constexpr int kBufSize = 256; |
| GLint params[kBufSize]; |
| glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(1, params[0]); // array_size |
| EXPECT_LE(0, params[1]); // array_stride |
| EXPECT_LE(0, params[2]); // block_index |
| EXPECT_EQ(0, params[3]); // is_row_major |
| EXPECT_EQ(8, params[4]); // matrix_stride |
| EXPECT_EQ(19, params[5]); // name_length |
| EXPECT_EQ(64, params[6]); // offset |
| |
| EXPECT_EQ(0, params[7]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[8]); // referenced_by_fragment_shader |
| // TODO(jiajia.qin@intel.com): referenced_by_compute_shader is not |
| // correctly handled. http://anglebug.com/1920. |
| // EXPECT_EQ(1, params[9]); // referenced_by_compute_shader |
| EXPECT_EQ(3, params[10]); // top_level_array_size |
| EXPECT_EQ(48, params[11]); // top_level_array_stride |
| EXPECT_EQ(GL_FLOAT_MAT2, params[12]); // type |
| |
| index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockOut.a[0][0]"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(16, length); |
| EXPECT_EQ("blockOut.a[0][0]", std::string(name)); |
| |
| glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length, |
| params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(3, params[0]); // array_size |
| EXPECT_LE(0, params[1]); // array_stride |
| EXPECT_LE(0, params[2]); // block_index |
| EXPECT_EQ(0, params[3]); // is_row_major |
| EXPECT_EQ(0, params[4]); // matrix_stride |
| EXPECT_EQ(17, params[5]); // name_length |
| EXPECT_EQ(4, params[6]); // offset |
| |
| EXPECT_EQ(0, params[7]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[8]); // referenced_by_fragment_shader |
| EXPECT_EQ(1, params[9]); // referenced_by_compute_shader |
| EXPECT_EQ(4, params[10]); // top_level_array_size |
| EXPECT_EQ(12, params[11]); // top_level_array_stride |
| EXPECT_EQ(GL_UNSIGNED_INT, params[12]); // type |
| } |
| |
| // Tests the resource property query for shader storage block can be done correctly. |
| TEST_P(ProgramInterfaceTestES31, GetShaderStorageBlockProperties) |
| { |
| // TODO(jiajia.qin@intel.com): Don't skip this test once non-simple SSBO sentences are supported |
| // on d3d backend. http://anglebug.com/1951 |
| ANGLE_SKIP_TEST_IF(IsD3D11()); |
| |
| constexpr char kVS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "struct S {\n" |
| " vec3 a;\n" |
| " ivec2 b[4];\n" |
| "};\n" |
| "layout(std140) buffer blockName0 {\n" |
| " S s0;\n" |
| " vec2 v0;\n" |
| " S s1[2];\n" |
| " uint u0;\n" |
| "};\n" |
| "layout(binding = 1) buffer blockName1 {\n" |
| " uint u1[2];\n" |
| " float f1;\n" |
| "} instanceName1[2];\n" |
| "layout(binding = 2) buffer blockName2 {\n" |
| " uint u2;\n" |
| " float f2;\n" |
| "};\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(instanceName1[0].f1, s1[0].a);\n" |
| "}\n"; |
| |
| constexpr char kFS[] = |
| "#version 310 es\n" |
| "precision highp float;\n" |
| "uniform vec4 color;\n" |
| "out vec4 oColor;\n" |
| "void main()\n" |
| "{\n" |
| " oColor = color;\n" |
| "}"; |
| |
| ANGLE_GL_PROGRAM(program, kVS, kFS); |
| |
| GLuint index = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "blockName0"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLchar name[64]; |
| GLsizei length; |
| glGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(10, length); |
| EXPECT_EQ("blockName0", std::string(name)); |
| |
| GLenum props[] = {GL_ACTIVE_VARIABLES, |
| GL_BUFFER_BINDING, |
| GL_NUM_ACTIVE_VARIABLES, |
| GL_BUFFER_DATA_SIZE, |
| GL_NAME_LENGTH, |
| GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, |
| GL_REFERENCED_BY_COMPUTE_SHADER}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| constexpr int kBufSize = 256; |
| GLint params[kBufSize]; |
| |
| glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, index, propCount, props, kBufSize, |
| &length, params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(13, length); |
| EXPECT_LE(0, params[0]); // active_variables s0.a |
| EXPECT_LE(0, params[1]); // active_variables s0.b |
| EXPECT_LE(0, params[2]); // active_variables v0 |
| EXPECT_LE(0, params[3]); // active_variables s1[0].a |
| EXPECT_LE(0, params[4]); // active_variables s1[0].b |
| EXPECT_LE(0, params[5]); // active_variables u0 |
| EXPECT_EQ(0, params[6]); // buffer_binding |
| EXPECT_EQ(6, params[7]); // num_active_variables |
| EXPECT_LE(0, params[8]); // buffer_data_size |
| EXPECT_EQ(11, params[9]); // name_length |
| |
| EXPECT_EQ(1, params[10]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[11]); // referenced_by_fragment_shader |
| EXPECT_EQ(0, params[12]); // referenced_by_compute_shader |
| |
| index = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "blockName1"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| glGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, index, sizeof(name), &length, name); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(13, length); |
| EXPECT_EQ("blockName1[0]", std::string(name)); |
| } |
| |
| // Tests querying the program resources of atomic counter buffers. |
| TEST_P(ProgramInterfaceTestES31, GetAtomicCounterProperties) |
| { |
| constexpr char kCSSource[] = R"(#version 310 es |
| layout(local_size_x=1, local_size_y=1, local_size_z=1) in; |
| layout(binding = 0) uniform atomic_uint acbase; |
| layout(binding = 0, offset = 8) uniform atomic_uint ac[1]; |
| layout(binding = 0) uniform atomic_uint ac2; |
| |
| void main() |
| { |
| atomicCounter(acbase); |
| atomicCounter(ac[0]); |
| atomicCounter(ac2); |
| })"; |
| |
| ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource); |
| |
| GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_NE(GL_INVALID_INDEX, index); |
| |
| GLenum props[] = {GL_ATOMIC_COUNTER_BUFFER_INDEX}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| GLint atomicIndex; |
| GLsizei length; |
| |
| glGetProgramResourceiv(program, GL_UNIFORM, index, propCount, props, 1, &length, &atomicIndex); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(1, length); |
| EXPECT_LE(0, atomicIndex); |
| |
| GLenum atomicProps[] = {GL_ACTIVE_VARIABLES, |
| GL_BUFFER_BINDING, |
| GL_NUM_ACTIVE_VARIABLES, |
| GL_BUFFER_DATA_SIZE, |
| GL_REFERENCED_BY_VERTEX_SHADER, |
| GL_REFERENCED_BY_FRAGMENT_SHADER, |
| GL_REFERENCED_BY_COMPUTE_SHADER}; |
| |
| GLsizei atomicPropsCount = static_cast<GLsizei>(ArraySize(atomicProps)); |
| constexpr int kBufSize = 256; |
| GLint params[kBufSize]; |
| GLsizei length2; |
| |
| glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, atomicIndex, atomicPropsCount, |
| atomicProps, kBufSize, &length2, params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(9, length2); |
| |
| EXPECT_LE(0, params[0]); // active_variables acbase |
| EXPECT_LE(0, params[1]); // active_variables ac[1] |
| EXPECT_LE(0, params[2]); // active_variables ac2 |
| EXPECT_EQ(0, params[3]); // buffer_binding |
| EXPECT_EQ(3, params[4]); // num_active_variables |
| EXPECT_EQ(16, params[5]); // buffer_data_size |
| |
| EXPECT_EQ(0, params[6]); // referenced_by_vertex_shader |
| EXPECT_EQ(0, params[7]); // referenced_by_fragment_shader |
| EXPECT_EQ(1, params[8]); // referenced_by_compute_shader |
| } |
| |
| // Tests transform feedback varying qeury works correctly. |
| TEST_P(ProgramInterfaceTestES31, QueryTransformFeedbackVarying) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| in vec3 position; |
| out float outSingleType; |
| out vec2 outWholeArray[2]; |
| out vec3 outArrayElements[16]; |
| void main() { |
| outSingleType = 0.0; |
| outWholeArray[0] = vec2(position); |
| outArrayElements[7] = vec3(0, 0, 0); |
| outArrayElements[15] = position; |
| gl_Position = vec4(position, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(#version 310 es |
| precision mediump float; |
| out vec4 color; |
| in float outSingleType; |
| in vec2 outWholeArray[2]; |
| in vec3 outArrayElements[16]; |
| void main() { |
| color = vec4(0); |
| })"; |
| |
| std::vector<std::string> tfVaryings; |
| tfVaryings.push_back("outArrayElements[7]"); |
| tfVaryings.push_back("outArrayElements[15]"); |
| tfVaryings.push_back("outSingleType"); |
| tfVaryings.push_back("outWholeArray"); |
| |
| GLuint program = |
| CompileProgramWithTransformFeedback(kVS, kFS, tfVaryings, GL_INTERLEAVED_ATTRIBS); |
| ASSERT_NE(0u, program); |
| |
| GLint num; |
| glGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_ACTIVE_RESOURCES, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(4, num); |
| |
| glGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_MAX_NAME_LENGTH, &num); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(21, num); // outArrayElements[15] |
| |
| // GLES 3.10, Page 77: |
| // For TRANSFORM_FEEDBACK_VARYING, the active resource list will use the variable order |
| // specified in the most recent call to TransformFeedbackVaryings before the last call to |
| // LinkProgram. |
| GLuint index = |
| glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outArrayElements[7]"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(0u, index); |
| index = |
| glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outArrayElements[15]"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(1u, index); |
| index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outSingleType"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(2u, index); |
| index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outWholeArray"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(3u, index); |
| |
| // GLES 3.10, Page 80: |
| // For TRANSFORM_FEEDBACK_VARYING resources, name must match one of the variables to be captured |
| // as specified by a previous call to TransformFeedbackVaryings. Otherwise, INVALID_INDEX is |
| // returned. |
| // If name does not match a resource as described above, the value INVALID_INDEX is returned, |
| // but no GL error is generated. |
| index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outWholeArray[0]"); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(GL_INVALID_INDEX, index); |
| |
| GLenum props[] = {GL_TYPE, GL_ARRAY_SIZE, GL_NAME_LENGTH}; |
| GLsizei propCount = static_cast<GLsizei>(ArraySize(props)); |
| GLint params[ArraySize(props)]; |
| GLsizei length = 0; |
| // Query properties of 'outArrayElements[15]'. |
| glGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, 1, propCount, props, propCount, |
| &length, params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(GL_FLOAT_VEC3, params[0]); // type |
| EXPECT_EQ(1, params[1]); // array_size |
| EXPECT_EQ(21, params[2]); // name_length |
| |
| // Query properties of 'outWholeArray'. |
| glGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, 3, propCount, props, propCount, |
| &length, params); |
| EXPECT_GL_NO_ERROR(); |
| EXPECT_EQ(propCount, length); |
| EXPECT_EQ(GL_FLOAT_VEC2, params[0]); // type |
| EXPECT_EQ(2, params[1]); // array_size |
| EXPECT_EQ(14, params[2]); // name_length |
| |
| glDeleteProgram(program); |
| } |
| |
| ANGLE_INSTANTIATE_TEST_ES31(ProgramInterfaceTestES31); |
| |
| } // anonymous namespace |