зеркало из https://github.com/AvaloniaUI/angle.git
CollectVariables: Don't include block name in field name.
The spec mandates that the instance name of a block determines how the active uniform name for this field is reported. However, our handling of this was a bit bugged. We would include the proper prefix on the compiler-side, but this mangled the hashing, and was also not strictly needed. We now also expose the instance name, so we can determine the proper prefix for variable linking on the GL-side of things. This also is consistent with how we handle other spec issues, where the GL-side handles the GL-API specific functionality. This also allows us to fix name hashing of instanced uniform blocks, which was previously broken because we would hash the full name of the active uniform, instead of just the field. BUG=angleproject:1306 Change-Id: I06ace6dbc3f75fdd8129677360dcc142aa89136e Reviewed-on: https://chromium-review.googlesource.com/326681 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
15e890e601
Коммит
39046169da
|
@ -48,7 +48,7 @@ typedef unsigned int GLenum;
|
|||
|
||||
// Version number for shader translation API.
|
||||
// It is incremented every time the API changes.
|
||||
#define ANGLE_SH_VERSION 142
|
||||
#define ANGLE_SH_VERSION 143
|
||||
|
||||
typedef enum {
|
||||
SH_GLES2_SPEC = 0x8B40,
|
||||
|
|
|
@ -200,6 +200,9 @@ struct COMPILER_EXPORT InterfaceBlock
|
|||
InterfaceBlock(const InterfaceBlock &other);
|
||||
InterfaceBlock &operator=(const InterfaceBlock &other);
|
||||
|
||||
// Fields from blocks with non-empty instance names are prefixed with the block name.
|
||||
std::string fieldPrefix() const;
|
||||
|
||||
std::string name;
|
||||
std::string mappedName;
|
||||
std::string instanceName;
|
||||
|
@ -210,6 +213,6 @@ struct COMPILER_EXPORT InterfaceBlock
|
|||
std::vector<InterfaceBlockField> fields;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace sh
|
||||
|
||||
#endif // GLSLANG_SHADERVARS_H_
|
||||
|
|
|
@ -393,4 +393,9 @@ InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
std::string InterfaceBlock::fieldPrefix() const
|
||||
{
|
||||
return instanceName.empty() ? "" : name;
|
||||
}
|
||||
|
||||
} // namespace sh
|
||||
|
|
|
@ -16,18 +16,6 @@ namespace sh
|
|||
namespace
|
||||
{
|
||||
|
||||
TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
|
||||
{
|
||||
if (interfaceBlock.hasInstanceName())
|
||||
{
|
||||
return interfaceBlock.name() + "." + field.name();
|
||||
}
|
||||
else
|
||||
{
|
||||
return field.name();
|
||||
}
|
||||
}
|
||||
|
||||
BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
|
||||
{
|
||||
switch (blockStorage)
|
||||
|
@ -559,16 +547,12 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
|
|||
interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
|
||||
|
||||
// Gather field information
|
||||
const TFieldList &fieldList = blockType->fields();
|
||||
|
||||
for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
|
||||
for (const TField *field : blockType->fields())
|
||||
{
|
||||
const TField &field = *fieldList[fieldIndex];
|
||||
const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
|
||||
const TType &fieldType = *field.type();
|
||||
const TType &fieldType = *field->type();
|
||||
|
||||
NameHashingTraverser traverser(mHashFunction, mSymbolTable);
|
||||
traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
|
||||
traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
|
||||
|
||||
interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
|
||||
}
|
||||
|
|
|
@ -2377,7 +2377,7 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
|
|||
// Track the first and last uniform index to determine the range of active uniforms in the
|
||||
// block.
|
||||
size_t firstBlockUniformIndex = mData.mUniforms.size();
|
||||
defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex);
|
||||
defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(), blockIndex);
|
||||
size_t lastBlockUniformIndex = mData.mUniforms.size();
|
||||
|
||||
std::vector<unsigned int> blockUniformIndexes;
|
||||
|
|
|
@ -2063,8 +2063,8 @@ size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
|
|||
encoder = &hlslEncoder;
|
||||
}
|
||||
|
||||
GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
|
||||
&mBlockInfo);
|
||||
GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
|
||||
interfaceBlock.isRowMajorLayout, &mBlockInfo);
|
||||
|
||||
return encoder->getBlockSize();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
// Some tests for shader inspection
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "angle_gl.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
|
@ -18,14 +20,10 @@
|
|||
class CollectVariablesTest : public testing::Test
|
||||
{
|
||||
public:
|
||||
CollectVariablesTest(GLenum shaderType)
|
||||
: mShaderType(shaderType),
|
||||
mTranslator(nullptr)
|
||||
{
|
||||
}
|
||||
CollectVariablesTest(GLenum shaderType) : mShaderType(shaderType) {}
|
||||
|
||||
protected:
|
||||
virtual void SetUp()
|
||||
void SetUp() override
|
||||
{
|
||||
ShBuiltInResources resources;
|
||||
ShInitBuiltInResources(&resources);
|
||||
|
@ -34,16 +32,10 @@ class CollectVariablesTest : public testing::Test
|
|||
initTranslator(resources);
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
SafeDelete(mTranslator);
|
||||
}
|
||||
|
||||
void initTranslator(const ShBuiltInResources &resources)
|
||||
{
|
||||
SafeDelete(mTranslator);
|
||||
mTranslator = new TranslatorGLSL(
|
||||
mShaderType, SH_GLES3_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT);
|
||||
mTranslator.reset(
|
||||
new TranslatorGLSL(mShaderType, SH_GLES3_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT));
|
||||
ASSERT_TRUE(mTranslator->Init(resources));
|
||||
}
|
||||
|
||||
|
@ -113,8 +105,14 @@ class CollectVariablesTest : public testing::Test
|
|||
*outResult = &outputVariable;
|
||||
}
|
||||
|
||||
void compile(const std::string &shaderString)
|
||||
{
|
||||
const char *shaderStrings[] = {shaderString.c_str()};
|
||||
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
|
||||
}
|
||||
|
||||
GLenum mShaderType;
|
||||
TranslatorGLSL *mTranslator;
|
||||
std::unique_ptr<TranslatorGLSL> mTranslator;
|
||||
};
|
||||
|
||||
class CollectVertexVariablesTest : public CollectVariablesTest
|
||||
|
@ -139,8 +137,7 @@ TEST_F(CollectFragmentVariablesTest, SimpleOutputVar)
|
|||
" out_fragColor = vec4(1.0);\n"
|
||||
"}\n";
|
||||
|
||||
const char *shaderStrings[] = { shaderString.c_str() };
|
||||
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
|
||||
compile(shaderString);
|
||||
|
||||
const auto &outputVariables = mTranslator->getOutputVariables();
|
||||
ASSERT_EQ(1u, outputVariables.size());
|
||||
|
@ -165,8 +162,7 @@ TEST_F(CollectFragmentVariablesTest, LocationOutputVar)
|
|||
" out_fragColor = vec4(1.0);\n"
|
||||
"}\n";
|
||||
|
||||
const char *shaderStrings[] = { shaderString.c_str() };
|
||||
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
|
||||
compile(shaderString);
|
||||
|
||||
const auto &outputVariables = mTranslator->getOutputVariables();
|
||||
ASSERT_EQ(1u, outputVariables.size());
|
||||
|
@ -190,8 +186,7 @@ TEST_F(CollectVertexVariablesTest, LocationAttribute)
|
|||
" gl_Position = in_Position;\n"
|
||||
"}\n";
|
||||
|
||||
const char *shaderStrings[] = { shaderString.c_str() };
|
||||
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
|
||||
compile(shaderString);
|
||||
|
||||
const std::vector<sh::Attribute> &attributes = mTranslator->getAttributes();
|
||||
ASSERT_EQ(1u, attributes.size());
|
||||
|
@ -217,8 +212,7 @@ TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock)
|
|||
" 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));
|
||||
compile(shaderString);
|
||||
|
||||
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
|
||||
ASSERT_EQ(1u, interfaceBlocks.size());
|
||||
|
@ -254,8 +248,7 @@ TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock)
|
|||
" 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));
|
||||
compile(shaderString);
|
||||
|
||||
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
|
||||
ASSERT_EQ(1u, interfaceBlocks.size());
|
||||
|
@ -266,6 +259,7 @@ TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock)
|
|||
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
|
||||
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
|
||||
EXPECT_EQ("b", interfaceBlock.name);
|
||||
EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
|
||||
EXPECT_TRUE(interfaceBlock.staticUse);
|
||||
|
||||
ASSERT_EQ(1u, interfaceBlock.fields.size());
|
||||
|
@ -275,7 +269,7 @@ TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock)
|
|||
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_EQ("f", field.name);
|
||||
EXPECT_FALSE(field.isRowMajorLayout);
|
||||
EXPECT_TRUE(field.fields.empty());
|
||||
}
|
||||
|
@ -292,8 +286,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
|
|||
" 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));
|
||||
compile(shaderString);
|
||||
|
||||
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
|
||||
ASSERT_EQ(1u, interfaceBlocks.size());
|
||||
|
@ -336,8 +329,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
|
|||
" 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));
|
||||
compile(shaderString);
|
||||
|
||||
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
|
||||
ASSERT_EQ(1u, interfaceBlocks.size());
|
||||
|
@ -348,6 +340,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
|
|||
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
|
||||
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
|
||||
EXPECT_EQ("b", interfaceBlock.name);
|
||||
EXPECT_EQ("instanceName", interfaceBlock.instanceName);
|
||||
EXPECT_TRUE(interfaceBlock.staticUse);
|
||||
|
||||
ASSERT_EQ(1u, interfaceBlock.fields.size());
|
||||
|
@ -356,7 +349,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
|
|||
|
||||
EXPECT_TRUE(field.isStruct());
|
||||
EXPECT_TRUE(field.staticUse);
|
||||
EXPECT_EQ("b.s", field.name);
|
||||
EXPECT_EQ("s", field.name);
|
||||
EXPECT_FALSE(field.isRowMajorLayout);
|
||||
|
||||
const sh::ShaderVariable &member = field.fields[0];
|
||||
|
@ -380,8 +373,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
|
|||
" gl_Position = vec4(s.m);\n"
|
||||
"}\n";
|
||||
|
||||
const char *shaderStrings[] = { shaderString.c_str() };
|
||||
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
|
||||
compile(shaderString);
|
||||
|
||||
const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
|
||||
ASSERT_EQ(1u, interfaceBlocks.size());
|
||||
|
@ -423,8 +415,7 @@ TEST_F(CollectVertexVariablesTest, VaryingInterpolation)
|
|||
" vary = 1.0;\n"
|
||||
"}\n";
|
||||
|
||||
const char *shaderStrings[] = { shaderString.c_str() };
|
||||
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
|
||||
compile(shaderString);
|
||||
|
||||
const std::vector<sh::Varying> &varyings = mTranslator->getVaryings();
|
||||
ASSERT_EQ(2u, varyings.size());
|
||||
|
@ -654,3 +645,96 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary
|
|||
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
|
||||
EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
|
||||
}
|
||||
|
||||
static khronos_uint64_t SimpleTestHash(const char *str, size_t len)
|
||||
{
|
||||
return static_cast<uint64_t>(len);
|
||||
}
|
||||
|
||||
class CollectHashedVertexVariablesTest : public CollectVertexVariablesTest
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Initialize the translate with a hash function
|
||||
ShBuiltInResources resources;
|
||||
ShInitBuiltInResources(&resources);
|
||||
resources.HashFunction = SimpleTestHash;
|
||||
initTranslator(resources);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CollectHashedVertexVariablesTest, InstancedInterfaceBlock)
|
||||
{
|
||||
const std::string &shaderString =
|
||||
"#version 300 es\n"
|
||||
"uniform blockName {\n"
|
||||
" float field;\n"
|
||||
"} blockInstance;"
|
||||
"void main() {\n"
|
||||
" gl_Position = vec4(blockInstance.field, 0.0, 0.0, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
compile(shaderString);
|
||||
|
||||
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("blockName", interfaceBlock.name);
|
||||
EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
|
||||
EXPECT_EQ("webgl_9", interfaceBlock.mappedName);
|
||||
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("field", field.name);
|
||||
EXPECT_EQ("webgl_5", field.mappedName);
|
||||
EXPECT_FALSE(field.isRowMajorLayout);
|
||||
EXPECT_TRUE(field.fields.empty());
|
||||
}
|
||||
|
||||
TEST_F(CollectHashedVertexVariablesTest, StructUniform)
|
||||
{
|
||||
const std::string &shaderString =
|
||||
"#version 300 es\n"
|
||||
"struct sType {\n"
|
||||
" float field;\n"
|
||||
"};"
|
||||
"uniform sType u;"
|
||||
"void main() {\n"
|
||||
" gl_Position = vec4(u.field, 0.0, 0.0, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
compile(shaderString);
|
||||
|
||||
const auto &uniforms = mTranslator->getUniforms();
|
||||
ASSERT_EQ(1u, uniforms.size());
|
||||
|
||||
const sh::Uniform &uniform = uniforms[0];
|
||||
|
||||
EXPECT_EQ(0u, uniform.arraySize);
|
||||
EXPECT_EQ("u", uniform.name);
|
||||
EXPECT_EQ("webgl_1", uniform.mappedName);
|
||||
EXPECT_TRUE(uniform.staticUse);
|
||||
|
||||
ASSERT_EQ(1u, uniform.fields.size());
|
||||
|
||||
const sh::ShaderVariable &field = uniform.fields[0];
|
||||
|
||||
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
|
||||
// EXPECT_TRUE(field.staticUse); // we don't yet support struct static use
|
||||
EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
|
||||
EXPECT_EQ("field", field.name);
|
||||
EXPECT_EQ("webgl_5", field.mappedName);
|
||||
EXPECT_TRUE(field.fields.empty());
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче