blob: 0c3160e6fe042d35d542518120149e8917f8b6b2 [file] [log] [blame]
//
// Copyright (c) 2014 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.
//
// CollectVariables_test.cpp:
// Some tests for shader inspection
//
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "GLSLANG/ShaderLang.h"
#include "compiler/translator/TranslatorGLSL.h"
#define EXPECT_GLENUM_EQ(expected, actual) \
EXPECT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
class CollectVariablesTest : public testing::Test
{
public:
CollectVariablesTest(GLenum shaderType)
: mShaderType(shaderType)
{}
protected:
virtual void SetUp()
{
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
resources.MaxDrawBuffers = 8;
mTranslator = new TranslatorGLSL(mShaderType, SH_GLES2_SPEC);
ASSERT_TRUE(mTranslator->Init(resources));
}
virtual void TearDown()
{
delete mTranslator;
}
GLenum mShaderType;
TranslatorGLSL *mTranslator;
};
class CollectVertexVariablesTest : public CollectVariablesTest
{
public:
CollectVertexVariablesTest() : CollectVariablesTest(GL_VERTEX_SHADER) {}
};
class CollectFragmentVariablesTest : public CollectVariablesTest
{
public:
CollectFragmentVariablesTest() : CollectVariablesTest(GL_FRAGMENT_SHADER) {}
};
TEST_F(CollectFragmentVariablesTest, SimpleOutputVar)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 out_fragColor;\n"
"void main() {\n"
" out_fragColor = vec4(1.0);\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::Attribute> &outputVariables = mTranslator->getOutputVariables();
ASSERT_EQ(1u, outputVariables.size());
const sh::Attribute &outputVariable = outputVariables[0];
EXPECT_EQ(0u, outputVariable.arraySize);
EXPECT_EQ(-1, outputVariable.location);
EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision);
EXPECT_TRUE(outputVariable.staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type);
EXPECT_EQ("out_fragColor", outputVariable.name);
}
TEST_F(CollectFragmentVariablesTest, LocationOutputVar)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"layout(location=5) out vec4 out_fragColor;\n"
"void main() {\n"
" out_fragColor = vec4(1.0);\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::Attribute> &outputVariables = mTranslator->getOutputVariables();
ASSERT_EQ(1u, outputVariables.size());
const sh::Attribute &outputVariable = outputVariables[0];
EXPECT_EQ(0u, outputVariable.arraySize);
EXPECT_EQ(5, outputVariable.location);
EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision);
EXPECT_TRUE(outputVariable.staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type);
EXPECT_EQ("out_fragColor", outputVariable.name);
}
TEST_F(CollectVertexVariablesTest, LocationAttribute)
{
const std::string &shaderString =
"#version 300 es\n"
"layout(location=5) in vec4 in_Position;\n"
"void main() {\n"
" gl_Position = in_Position;\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::Attribute> &attributes = mTranslator->getAttributes();
ASSERT_EQ(1u, attributes.size());
const sh::Attribute &attribute = attributes[0];
EXPECT_EQ(0u, attribute.arraySize);
EXPECT_EQ(5, attribute.location);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, attribute.precision);
EXPECT_TRUE(attribute.staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, attribute.type);
EXPECT_EQ("in_Position", attribute.name);
}
TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock)
{
const std::string &shaderString =
"#version 300 es\n"
"uniform b {\n"
" float f;\n"
"};"
"void main() {\n"
" gl_Position = vec4(f, 0.0, 0.0, 1.0);\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
ASSERT_EQ(1u, interfaceBlocks.size());
const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size());
const sh::InterfaceBlockField &field = interfaceBlock.fields[0];
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
EXPECT_TRUE(field.staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
EXPECT_EQ("f", field.name);
EXPECT_FALSE(field.isRowMajorLayout);
EXPECT_TRUE(field.fields.empty());
}
TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock)
{
const std::string &shaderString =
"#version 300 es\n"
"uniform b {\n"
" float f;\n"
"} blockInstance;"
"void main() {\n"
" gl_Position = vec4(blockInstance.f, 0.0, 0.0, 1.0);\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
ASSERT_EQ(1u, interfaceBlocks.size());
const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size());
const sh::InterfaceBlockField &field = interfaceBlock.fields[0];
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
EXPECT_TRUE(field.staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
EXPECT_EQ("b.f", field.name);
EXPECT_FALSE(field.isRowMajorLayout);
EXPECT_TRUE(field.fields.empty());
}
TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
{
const std::string &shaderString =
"#version 300 es\n"
"struct st { float f; };"
"uniform b {\n"
" st s;\n"
"};"
"void main() {\n"
" gl_Position = vec4(s.f, 0.0, 0.0, 1.0);\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
ASSERT_EQ(1u, interfaceBlocks.size());
const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size());
const sh::InterfaceBlockField &field = interfaceBlock.fields[0];
EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name);
EXPECT_FALSE(field.isRowMajorLayout);
const sh::ShaderVariable &member = field.fields[0];
// NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct());
EXPECT_EQ("f", member.name);
EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
}
TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
{
const std::string &shaderString =
"#version 300 es\n"
"struct st { float f; };"
"uniform b {\n"
" st s;\n"
"} instanceName;"
"void main() {\n"
" gl_Position = vec4(instanceName.s.f, 0.0, 0.0, 1.0);\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
ASSERT_EQ(1u, interfaceBlocks.size());
const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size());
const sh::InterfaceBlockField &field = interfaceBlock.fields[0];
EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse);
EXPECT_EQ("b.s", field.name);
EXPECT_FALSE(field.isRowMajorLayout);
const sh::ShaderVariable &member = field.fields[0];
// NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct());
EXPECT_EQ("f", member.name);
EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
}
TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
{
const std::string &shaderString =
"#version 300 es\n"
"struct st { mat2 m; };"
"layout(row_major) uniform b {\n"
" st s;\n"
"};"
"void main() {\n"
" gl_Position = vec4(s.m);\n"
"}\n";
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
ASSERT_EQ(1u, interfaceBlocks.size());
const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_TRUE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size());
const sh::InterfaceBlockField &field = interfaceBlock.fields[0];
EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name);
EXPECT_TRUE(field.isRowMajorLayout);
const sh::ShaderVariable &member = field.fields[0];
// NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct());
EXPECT_EQ("m", member.name);
EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
}