Commit d5512cd4 by Jamie Madill

Collect shader outputs and interface block information.

This paves the way for returning ES3-specific info from the shader translator with the new query methods. BUG=angle:466 Change-Id: Ib13cdb604854cdf11e9dc00dd94f18eadc946561 Reviewed-on: https://chromium-review.googlesource.com/206770Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org>
parent 0b7e5d8c
...@@ -157,20 +157,32 @@ typedef std::vector<BlockMemberInfo> BlockMemberInfoArray; ...@@ -157,20 +157,32 @@ typedef std::vector<BlockMemberInfo> BlockMemberInfoArray;
struct InterfaceBlock struct InterfaceBlock
{ {
InterfaceBlock()
: arraySize(0),
dataSize(0),
layout(BLOCKLAYOUT_PACKED),
isRowMajorLayout(false),
staticUse(false),
registerIndex(-1)
{}
InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex) InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex)
: name(name), : name(name),
arraySize(arraySize), arraySize(arraySize),
dataSize(0), dataSize(0),
layout(BLOCKLAYOUT_SHARED), layout(BLOCKLAYOUT_SHARED),
isRowMajorLayout(false), isRowMajorLayout(false),
staticUse(false),
registerIndex(registerIndex) registerIndex(registerIndex)
{} {}
std::string name; std::string name;
std::string mappedName;
unsigned int arraySize; unsigned int arraySize;
size_t dataSize; size_t dataSize;
BlockLayoutType layout; BlockLayoutType layout;
bool isRowMajorLayout; bool isRowMajorLayout;
bool staticUse;
std::vector<InterfaceBlockField> fields; std::vector<InterfaceBlockField> fields;
std::vector<BlockMemberInfo> blockInfo; std::vector<BlockMemberInfo> blockInfo;
......
...@@ -487,7 +487,12 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) ...@@ -487,7 +487,12 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
void TCompiler::collectVariables(TIntermNode* root) void TCompiler::collectVariables(TIntermNode* root)
{ {
CollectVariables collect(&attributes, &uniforms, &varyings, hashFunction); CollectVariables collect(&attributes,
&outputVariables,
&uniforms,
&varyings,
&interfaceBlocks,
hashFunction);
root->traverse(&collect); root->traverse(&collect);
// For backwards compatiblity with ShGetVariableInfo, expand struct // For backwards compatiblity with ShGetVariableInfo, expand struct
......
...@@ -49,17 +49,6 @@ static void SetBlockLayout(InterfaceBlock *interfaceBlock, BlockLayoutType newLa ...@@ -49,17 +49,6 @@ static void SetBlockLayout(InterfaceBlock *interfaceBlock, BlockLayoutType newLa
} }
} }
static BlockLayoutType ConvertBlockLayoutType(TLayoutBlockStorage blockStorage)
{
switch (blockStorage)
{
case EbsPacked: return BLOCKLAYOUT_PACKED;
case EbsShared: return BLOCKLAYOUT_SHARED;
case EbsStd140: return BLOCKLAYOUT_STANDARD;
default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
}
}
static const char *UniformRegisterPrefix(const TType &type) static const char *UniformRegisterPrefix(const TType &type)
{ {
if (IsSampler(type.getBasicType())) if (IsSampler(type.getBasicType()))
...@@ -249,7 +238,7 @@ TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedIn ...@@ -249,7 +238,7 @@ TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedIn
mInterfaceBlockRegister += std::max(1u, arraySize); mInterfaceBlockRegister += std::max(1u, arraySize);
BlockLayoutType blockLayoutType = ConvertBlockLayoutType(interfaceBlock.blockStorage()); BlockLayoutType blockLayoutType = GetBlockLayoutType(interfaceBlock.blockStorage());
SetBlockLayout(&activeBlock, blockLayoutType); SetBlockLayout(&activeBlock, blockLayoutType);
if (interfaceBlock.matrixPacking() == EmpRowMajor) if (interfaceBlock.matrixPacking() == EmpRowMajor)
......
...@@ -79,7 +79,7 @@ TString DecoratePrivate(const TString &privateText) ...@@ -79,7 +79,7 @@ TString DecoratePrivate(const TString &privateText)
TString Decorate(const TString &string) TString Decorate(const TString &string)
{ {
if (string.compare(0, 3, "gl_")) if (string.compare(0, 3, "gl_") != 0)
{ {
return "_" + string; return "_" + string;
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/VariableInfo.h" #include "compiler/translator/VariableInfo.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
#include "common/utilities.h"
template <typename VarT> template <typename VarT>
static void ExpandUserDefinedVariable(const VarT &variable, static void ExpandUserDefinedVariable(const VarT &variable,
...@@ -85,7 +86,7 @@ static void ExpandUserDefinedVariable(const VarT &variable, ...@@ -85,7 +86,7 @@ static void ExpandUserDefinedVariable(const VarT &variable,
} }
template <class VarT> template <class VarT>
static VarT* findVariable(const TString &name, static VarT *FindVariable(const TString &name,
std::vector<VarT> *infoList) std::vector<VarT> *infoList)
{ {
// TODO(zmo): optimize this function. // TODO(zmo): optimize this function.
...@@ -94,16 +95,21 @@ static VarT* findVariable(const TString &name, ...@@ -94,16 +95,21 @@ static VarT* findVariable(const TString &name,
if ((*infoList)[ii].name.c_str() == name) if ((*infoList)[ii].name.c_str() == name)
return &((*infoList)[ii]); return &((*infoList)[ii]);
} }
return NULL; return NULL;
} }
CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs, CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
std::vector<sh::Attribute> *outputVariables,
std::vector<sh::Uniform> *uniforms, std::vector<sh::Uniform> *uniforms,
std::vector<sh::Varying> *varyings, std::vector<sh::Varying> *varyings,
std::vector<sh::InterfaceBlock> *interfaceBlocks,
ShHashFunction64 hashFunction) ShHashFunction64 hashFunction)
: mAttribs(attribs), : mAttribs(attribs),
mOutputVariables(outputVariables),
mUniforms(uniforms), mUniforms(uniforms),
mVaryings(varyings), mVaryings(varyings),
mInterfaceBlocks(interfaceBlocks),
mPointCoordAdded(false), mPointCoordAdded(false),
mFrontFacingAdded(false), mFrontFacingAdded(false),
mFragCoordAdded(false), mFragCoordAdded(false),
...@@ -120,17 +126,43 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) ...@@ -120,17 +126,43 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
{ {
ASSERT(symbol != NULL); ASSERT(symbol != NULL);
sh::ShaderVariable *var = NULL; sh::ShaderVariable *var = NULL;
const TString &symbolName = symbol->getSymbol();
if (sh::IsVarying(symbol->getQualifier())) if (sh::IsVarying(symbol->getQualifier()))
{ {
var = findVariable(symbol->getSymbol(), mVaryings); var = FindVariable(symbolName, mVaryings);
} }
else else if (symbol->getType() != EbtInterfaceBlock)
{ {
switch (symbol->getQualifier()) switch (symbol->getQualifier())
{ {
case EvqAttribute:
case EvqVertexIn:
var = FindVariable(symbolName, mAttribs);
break;
case EvqFragmentOut:
var = FindVariable(symbolName, mOutputVariables);
break;
case EvqUniform: case EvqUniform:
var = findVariable(symbol->getSymbol(), mUniforms); {
const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
if (interfaceBlock)
{
sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
ASSERT(namedBlock);
var = FindVariable(symbolName, &namedBlock->fields);
// Set static use on the parent interface block here
namedBlock->staticUse = true;
}
else
{
var = FindVariable(symbolName, mUniforms);
}
// It's an internal error to reference an undefined user uniform
ASSERT(symbolName.compare(0, 3, "gl_") == 0 || var);
}
break; break;
case EvqFragCoord: case EvqFragCoord:
if (!mFragCoordAdded) if (!mFragCoordAdded)
...@@ -224,6 +256,36 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, ...@@ -224,6 +256,36 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
infoList->push_back(attribute); infoList->push_back(attribute);
} }
template <>
void CollectVariables::visitVariable(const TIntermSymbol *variable,
std::vector<sh::InterfaceBlock> *infoList) const
{
sh::InterfaceBlock interfaceBlock;
const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
bool isRowMajor = (blockType->matrixPacking() == EmpRowMajor);
interfaceBlock.name = blockType->name().c_str();
interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
interfaceBlock.arraySize = variable->getArraySize();
interfaceBlock.isRowMajorLayout = isRowMajor;
interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage());
ASSERT(blockType);
const TFieldList &blockFields = blockType->fields();
for (size_t fieldIndex = 0; fieldIndex < blockFields.size(); fieldIndex++)
{
const TField *field = blockFields[fieldIndex];
ASSERT(field);
sh::GetInterfaceBlockFieldTraverser traverser(&interfaceBlock.fields, isRowMajor);
traverser.traverse(*field->type(), field->name());
}
infoList->push_back(interfaceBlock);
}
template <typename VarT> template <typename VarT>
void CollectVariables::visitVariable(const TIntermSymbol *variable, void CollectVariables::visitVariable(const TIntermSymbol *variable,
std::vector<VarT> *infoList) const std::vector<VarT> *infoList) const
...@@ -258,9 +320,16 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) ...@@ -258,9 +320,16 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
case EOpDeclaration: case EOpDeclaration:
{ {
const TIntermSequence &sequence = node->getSequence(); const TIntermSequence &sequence = node->getSequence();
TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); const TIntermTyped &typedNode = *sequence.front()->getAsTyped();
if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform || TQualifier qualifier = typedNode.getQualifier();
sh::IsVarying(qualifier))
if (typedNode.getBasicType() == EbtInterfaceBlock)
{
visitInfoList(sequence, mInterfaceBlocks);
}
else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
qualifier == EvqFragmentOut || qualifier == EvqUniform ||
sh::IsVarying(qualifier))
{ {
switch (qualifier) switch (qualifier)
{ {
...@@ -268,6 +337,9 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) ...@@ -268,6 +337,9 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
case EvqVertexIn: case EvqVertexIn:
visitInfoList(sequence, mAttribs); visitInfoList(sequence, mAttribs);
break; break;
case EvqFragmentOut:
visitInfoList(sequence, mOutputVariables);
break;
case EvqUniform: case EvqUniform:
visitInfoList(sequence, mUniforms); visitInfoList(sequence, mUniforms);
break; break;
......
...@@ -15,29 +15,35 @@ class CollectVariables : public TIntermTraverser ...@@ -15,29 +15,35 @@ class CollectVariables : public TIntermTraverser
{ {
public: public:
CollectVariables(std::vector<sh::Attribute> *attribs, CollectVariables(std::vector<sh::Attribute> *attribs,
std::vector<sh::Attribute> *outputVariables,
std::vector<sh::Uniform> *uniforms, std::vector<sh::Uniform> *uniforms,
std::vector<sh::Varying> *varyings, std::vector<sh::Varying> *varyings,
std::vector<sh::InterfaceBlock> *interfaceBlocks,
ShHashFunction64 hashFunction); ShHashFunction64 hashFunction);
virtual void visitSymbol(TIntermSymbol *symbol); virtual void visitSymbol(TIntermSymbol *symbol);
virtual bool visitAggregate(Visit, TIntermAggregate *node); virtual bool visitAggregate(Visit, TIntermAggregate *node);
private: private:
template <typename VarT>
void visitVariable(const TIntermSymbol *variable, std::vector<VarT> *infoList) const;
template <typename VarT>
void visitInfoList(const TIntermSequence &sequence, std::vector<VarT> *infoList) const;
std::vector<sh::Attribute> *mAttribs; std::vector<sh::Attribute> *mAttribs;
std::vector<sh::Attribute> *mOutputVariables;
std::vector<sh::Uniform> *mUniforms; std::vector<sh::Uniform> *mUniforms;
std::vector<sh::Varying> *mVaryings; std::vector<sh::Varying> *mVaryings;
std::vector<sh::InterfaceBlock> *mInterfaceBlocks;
std::map<std::string, sh::InterfaceBlockField *> mInterfaceBlockFields;
bool mPointCoordAdded; bool mPointCoordAdded;
bool mFrontFacingAdded; bool mFrontFacingAdded;
bool mFragCoordAdded; bool mFragCoordAdded;
ShHashFunction64 mHashFunction; ShHashFunction64 mHashFunction;
template <typename VarT>
void visitVariable(const TIntermSymbol *variable, std::vector<VarT> *infoList) const;
template <typename VarT>
void visitInfoList(const TIntermSequence &sequence, std::vector<VarT> *infoList) const;
}; };
// Expand struct variables to flattened lists of split variables // Expand struct variables to flattened lists of split variables
......
...@@ -342,4 +342,15 @@ void GetInterfaceBlockFieldTraverser::visitVariable(InterfaceBlockField *newFiel ...@@ -342,4 +342,15 @@ void GetInterfaceBlockFieldTraverser::visitVariable(InterfaceBlockField *newFiel
} }
} }
BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
{
switch (blockStorage)
{
case EbsPacked: return BLOCKLAYOUT_PACKED;
case EbsShared: return BLOCKLAYOUT_SHARED;
case EbsStd140: return BLOCKLAYOUT_STANDARD;
default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
}
}
} }
...@@ -32,6 +32,7 @@ bool IsVaryingIn(TQualifier qualifier); ...@@ -32,6 +32,7 @@ bool IsVaryingIn(TQualifier qualifier);
bool IsVaryingOut(TQualifier qualifier); bool IsVaryingOut(TQualifier qualifier);
bool IsVarying(TQualifier qualifier); bool IsVarying(TQualifier qualifier);
InterpolationType GetInterpolationType(TQualifier qualifier); InterpolationType GetInterpolationType(TQualifier qualifier);
BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage);
TString ArrayString(const TType &type); TString ArrayString(const TType &type);
template <typename VarT> template <typename VarT>
......
...@@ -1066,7 +1066,7 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, FragmentShader * ...@@ -1066,7 +1066,7 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, FragmentShader *
// This method needs to match OutputHLSL::decorate // This method needs to match OutputHLSL::decorate
std::string DynamicHLSL::decorateVariable(const std::string &name) std::string DynamicHLSL::decorateVariable(const std::string &name)
{ {
if (name.compare(0, 3, "gl_")) if (name.compare(0, 3, "gl_") != 0)
{ {
return "_" + name; return "_" + name;
} }
......
//
// 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"
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(0, outputVariable.arraySize);
EXPECT_EQ(-1, outputVariable.location);
EXPECT_EQ(GL_MEDIUM_FLOAT, outputVariable.precision);
EXPECT_EQ(true, outputVariable.staticUse);
EXPECT_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(0, outputVariable.arraySize);
EXPECT_EQ(5, outputVariable.location);
EXPECT_EQ(GL_MEDIUM_FLOAT, outputVariable.precision);
EXPECT_EQ(true, outputVariable.staticUse);
EXPECT_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(0, attribute.arraySize);
EXPECT_EQ(5, attribute.location);
EXPECT_EQ(GL_HIGH_FLOAT, attribute.precision);
EXPECT_EQ(true, attribute.staticUse);
EXPECT_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(0, interfaceBlock.arraySize);
EXPECT_EQ(false, interfaceBlock.isRowMajorLayout);
EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(true, interfaceBlock.staticUse);
ASSERT_EQ(1, interfaceBlock.fields.size());
const sh::InterfaceBlockField &field = interfaceBlock.fields[0];
EXPECT_EQ(GL_HIGH_FLOAT, field.precision);
EXPECT_EQ(true, field.staticUse);
EXPECT_EQ(GL_FLOAT, field.type);
EXPECT_EQ("f", field.name);
EXPECT_EQ(false, field.isRowMajorMatrix);
EXPECT_EQ(0, field.fields.size());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment