Commit a0a9e12d by Jamie Madill

translator: Add sh::OutputVariable type.

This replaces the dual-use of sh::Attribute, which can be a bit confusing to people expecting a literal output variable. Currently not used in Chromium, so should be safe to land. BUG=angleproject:1146 Change-Id: I436f2bc9dc4ddc3709369cb2baa344c6b13a21a2 Reviewed-on: https://chromium-review.googlesource.com/296683Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent beb81589
......@@ -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 139
#define ANGLE_SH_VERSION 140
typedef enum {
SH_GLES2_SPEC = 0x8B40,
......@@ -406,7 +406,7 @@ COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
COMPILER_EXPORT const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle);
typedef struct
......
......@@ -110,19 +110,39 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable
bool isSameUniformAtLinkTime(const Uniform &other) const;
};
struct COMPILER_EXPORT Attribute : public ShaderVariable
// An interface variable is a variable which passes data between the GL data structures and the
// shader execution: either vertex shader inputs or fragment shader outputs. These variables can
// have integer locations to pass back to the GL API.
struct COMPILER_EXPORT InterfaceVariable : public ShaderVariable
{
InterfaceVariable();
~InterfaceVariable();
InterfaceVariable(const InterfaceVariable &other);
InterfaceVariable &operator=(const InterfaceVariable &other);
bool operator==(const InterfaceVariable &other) const;
bool operator!=(const InterfaceVariable &other) const { return !operator==(other); }
int location;
};
struct COMPILER_EXPORT Attribute : public InterfaceVariable
{
Attribute();
~Attribute();
Attribute(const Attribute &other);
Attribute &operator=(const Attribute &other);
bool operator==(const Attribute &other) const;
bool operator!=(const Attribute &other) const
{
return !operator==(other);
}
bool operator!=(const Attribute &other) const { return !operator==(other); }
};
int location;
struct COMPILER_EXPORT OutputVariable : public InterfaceVariable
{
OutputVariable();
~OutputVariable();
OutputVariable(const OutputVariable &other);
OutputVariable &operator=(const OutputVariable &other);
bool operator==(const OutputVariable &other) const;
bool operator!=(const OutputVariable &other) const { return !operator==(other); }
};
struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
......
......@@ -420,7 +420,7 @@ static void PrintActiveVariables(ShHandle compiler)
const std::vector<sh::Uniform> *uniforms = ShGetUniforms(compiler);
const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler);
const std::vector<sh::Attribute> *attributes = ShGetAttributes(compiler);
const std::vector<sh::Attribute> *outputs = ShGetOutputVariables(compiler);
const std::vector<sh::OutputVariable> *outputs = ShGetOutputVariables(compiler);
for (size_t varCategory = 0; varCategory < 4; ++varCategory)
{
size_t numVars = 0;
......
......@@ -89,7 +89,7 @@ class TCompiler : public TShHandleBase
void clearResults();
const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
const std::vector<sh::Attribute> &getOutputVariables() const { return outputVariables; }
const std::vector<sh::OutputVariable> &getOutputVariables() const { return outputVariables; }
const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
const std::vector<sh::Varying> &getVaryings() const { return varyings; }
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
......@@ -158,7 +158,7 @@ class TCompiler : public TShHandleBase
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
std::vector<sh::Attribute> attributes;
std::vector<sh::Attribute> outputVariables;
std::vector<sh::OutputVariable> outputVariables;
std::vector<sh::Uniform> uniforms;
std::vector<sh::ShaderVariable> expandedUniforms;
std::vector<sh::Varying> varyings;
......
......@@ -23,15 +23,6 @@
namespace
{
enum ShaderVariableType
{
SHADERVAR_UNIFORM,
SHADERVAR_VARYING,
SHADERVAR_ATTRIBUTE,
SHADERVAR_OUTPUTVARIABLE,
SHADERVAR_INTERFACEBLOCK
};
bool isInitialized = false;
//
......@@ -40,36 +31,40 @@ bool isInitialized = false;
//
template <typename VarT>
const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType);
const std::vector<VarT> *GetVariableList(const TCompiler *compiler);
template <>
const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler)
{
return &compiler->getUniforms();
}
template <>
const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler)
{
return &compiler->getVaryings();
}
template <>
const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType)
const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler)
{
return &compiler->getAttributes();
}
template <>
const std::vector<sh::OutputVariable> *GetVariableList(const TCompiler *compiler)
{
return (variableType == SHADERVAR_ATTRIBUTE ?
&compiler->getAttributes() :
&compiler->getOutputVariables());
return &compiler->getOutputVariables();
}
template <>
const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler)
{
return &compiler->getInterfaceBlocks();
}
template <typename VarT>
const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariableType variableType)
const std::vector<VarT> *GetShaderVariables(const ShHandle handle)
{
if (!handle)
{
......@@ -83,7 +78,7 @@ const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariabl
return NULL;
}
return GetVariableList<VarT>(compiler, variableType);
return GetVariableList<VarT>(compiler);
}
TCompiler *GetCompilerFromHandle(ShHandle handle)
......@@ -104,7 +99,7 @@ TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
}
#endif // ANGLE_ENABLE_HLSL
} // namespace anonymous
} // anonymous namespace
//
// Driver must call this first, once, before doing any other compiler operations.
......@@ -299,27 +294,27 @@ const std::map<std::string, std::string> *ShGetNameHashingMap(
const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle)
{
return GetShaderVariables<sh::Uniform>(handle, SHADERVAR_UNIFORM);
return GetShaderVariables<sh::Uniform>(handle);
}
const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle)
{
return GetShaderVariables<sh::Varying>(handle, SHADERVAR_VARYING);
return GetShaderVariables<sh::Varying>(handle);
}
const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle)
{
return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_ATTRIBUTE);
return GetShaderVariables<sh::Attribute>(handle);
}
const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle)
const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle)
{
return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_OUTPUTVARIABLE);
return GetShaderVariables<sh::OutputVariable>(handle);
}
const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle)
{
return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK);
return GetShaderVariables<sh::InterfaceBlock>(handle);
}
bool ShCheckVariablesWithinPackingLimits(
......
......@@ -217,31 +217,75 @@ bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
return ShaderVariable::isSameVariableAtLinkTime(other, true);
}
Attribute::Attribute()
: location(-1)
InterfaceVariable::InterfaceVariable() : location(-1)
{}
Attribute::~Attribute()
InterfaceVariable::~InterfaceVariable()
{}
Attribute::Attribute(const Attribute &other)
: ShaderVariable(other),
location(other.location)
InterfaceVariable::InterfaceVariable(const InterfaceVariable &other)
: ShaderVariable(other), location(other.location)
{}
Attribute &Attribute::operator=(const Attribute &other)
InterfaceVariable &InterfaceVariable::operator=(const InterfaceVariable &other)
{
ShaderVariable::operator=(other);
location = other.location;
return *this;
}
bool Attribute::operator==(const Attribute &other) const
bool InterfaceVariable::operator==(const InterfaceVariable &other) const
{
return (ShaderVariable::operator==(other) &&
location == other.location);
}
Attribute::Attribute()
{
}
Attribute::~Attribute()
{
}
Attribute::Attribute(const Attribute &other) : InterfaceVariable(other)
{
}
Attribute &Attribute::operator=(const Attribute &other)
{
InterfaceVariable::operator=(other);
return *this;
}
bool Attribute::operator==(const Attribute &other) const
{
return InterfaceVariable::operator==(other);
}
OutputVariable::OutputVariable()
{
}
OutputVariable::~OutputVariable()
{
}
OutputVariable::OutputVariable(const OutputVariable &other) : InterfaceVariable(other)
{
}
OutputVariable &OutputVariable::operator=(const OutputVariable &other)
{
InterfaceVariable::operator=(other);
return *this;
}
bool OutputVariable::operator==(const OutputVariable &other) const
{
return InterfaceVariable::operator==(other);
}
InterfaceBlockField::InterfaceBlockField()
: isRowMajorLayout(false)
{}
......
......@@ -129,7 +129,7 @@ VarT *FindVariable(const TString &name,
}
CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
std::vector<sh::Attribute> *outputVariables,
std::vector<sh::OutputVariable> *outputVariables,
std::vector<sh::Uniform> *uniforms,
std::vector<sh::Varying> *varyings,
std::vector<sh::InterfaceBlock> *interfaceBlocks,
......@@ -375,7 +375,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
case EvqFragColor:
if (!mFragColorAdded)
{
Attribute info;
OutputVariable info;
const char kName[] = "gl_FragColor";
info.name = kName;
info.mappedName = kName;
......@@ -390,7 +390,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
case EvqFragData:
if (!mFragDataAdded)
{
Attribute info;
OutputVariable info;
const char kName[] = "gl_FragData";
info.name = kName;
info.mappedName = kName;
......@@ -408,7 +408,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
case EvqFragDepth:
if (!mFragDepthAdded)
{
Attribute info;
OutputVariable info;
const char kName[] = "gl_FragDepthEXT";
info.name = kName;
info.mappedName = kName;
......@@ -426,7 +426,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
case EvqSecondaryFragColorEXT:
if (!mSecondaryFragColorEXTAdded)
{
Attribute info;
OutputVariable info;
const char kName[] = "gl_SecondaryFragColorEXT";
info.name = kName;
info.mappedName = kName;
......@@ -441,7 +441,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
case EvqSecondaryFragDataEXT:
if (!mSecondaryFragDataEXTAdded)
{
Attribute info;
OutputVariable info;
const char kName[] = "gl_SecondaryFragDataEXT";
info.name = kName;
info.mappedName = kName;
......@@ -508,6 +508,26 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
template <>
void CollectVariables::visitVariable(const TIntermSymbol *variable,
std::vector<OutputVariable> *infoList) const
{
ASSERT(variable);
const TType &type = variable->getType();
ASSERT(!type.getStruct());
OutputVariable attribute;
attribute.type = GLVariableType(type);
attribute.precision = GLVariablePrecision(type);
attribute.name = variable->getSymbol().c_str();
attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
attribute.location = variable->getType().getLayoutQualifier().location;
infoList->push_back(attribute);
}
template <>
void CollectVariables::visitVariable(const TIntermSymbol *variable,
std::vector<InterfaceBlock> *infoList) const
{
InterfaceBlock interfaceBlock;
......
......@@ -21,7 +21,7 @@ class CollectVariables : public TIntermTraverser
{
public:
CollectVariables(std::vector<Attribute> *attribs,
std::vector<Attribute> *outputVariables,
std::vector<OutputVariable> *outputVariables,
std::vector<Uniform> *uniforms,
std::vector<Varying> *varyings,
std::vector<InterfaceBlock> *interfaceBlocks,
......@@ -40,7 +40,7 @@ class CollectVariables : public TIntermTraverser
void visitInfoList(const TIntermSequence &sequence, std::vector<VarT> *infoList) const;
std::vector<Attribute> *mAttribs;
std::vector<Attribute> *mOutputVariables;
std::vector<OutputVariable> *mOutputVariables;
std::vector<Uniform> *mUniforms;
std::vector<Varying> *mVaryings;
std::vector<InterfaceBlock> *mInterfaceBlocks;
......
......@@ -1701,14 +1701,14 @@ void Program::linkOutputVariables()
if (fragmentShader->getShaderVersion() == 100)
return;
const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
const auto &shaderOutputVars = fragmentShader->getActiveOutputVariables();
// TODO(jmadill): any caps validation here?
for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size();
outputVariableIndex++)
{
const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
const sh::OutputVariable &outputVariable = shaderOutputVars[outputVariableIndex];
// Don't store outputs for gl_FragDepth, gl_FragColor, etc.
if (outputVariable.isBuiltIn())
......
......@@ -194,7 +194,7 @@ const std::vector<sh::Attribute> &Shader::getActiveAttributes() const
return mShader->getActiveAttributes();
}
const std::vector<sh::Attribute> &Shader::getActiveOutputVariables() const
const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables() const
{
return mShader->getActiveOutputVariables();
}
......@@ -219,7 +219,7 @@ std::vector<sh::Attribute> &Shader::getActiveAttributes()
return mShader->getActiveAttributes();
}
std::vector<sh::Attribute> &Shader::getActiveOutputVariables()
std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables()
{
return mShader->getActiveOutputVariables();
}
......
......@@ -71,13 +71,13 @@ class Shader : angle::NonCopyable
const std::vector<sh::Uniform> &getUniforms() const;
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const;
const std::vector<sh::Attribute> &getActiveAttributes() const;
const std::vector<sh::Attribute> &getActiveOutputVariables() const;
const std::vector<sh::OutputVariable> &getActiveOutputVariables() const;
std::vector<sh::Varying> &getVaryings();
std::vector<sh::Uniform> &getUniforms();
std::vector<sh::InterfaceBlock> &getInterfaceBlocks();
std::vector<sh::Attribute> &getActiveAttributes();
std::vector<sh::Attribute> &getActiveOutputVariables();
std::vector<sh::OutputVariable> &getActiveOutputVariables();
int getSemanticIndex(const std::string &attributeName) const;
......
......@@ -35,13 +35,16 @@ class ShaderImpl : angle::NonCopyable
const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; }
const std::vector<sh::Attribute> &getActiveAttributes() const { return mActiveAttributes; }
const std::vector<sh::Attribute> &getActiveOutputVariables() const { return mActiveOutputVariables; }
const std::vector<sh::OutputVariable> &getActiveOutputVariables() const
{
return mActiveOutputVariables;
}
std::vector<sh::Varying> &getVaryings() { return mVaryings; }
std::vector<sh::Uniform> &getUniforms() { return mUniforms; }
std::vector<sh::InterfaceBlock> &getInterfaceBlocks() { return mInterfaceBlocks; }
std::vector<sh::Attribute> &getActiveAttributes() { return mActiveAttributes; }
std::vector<sh::Attribute> &getActiveOutputVariables() { return mActiveOutputVariables; }
std::vector<sh::OutputVariable> &getActiveOutputVariables() { return mActiveOutputVariables; }
protected:
std::string mInfoLog;
......@@ -54,7 +57,7 @@ class ShaderImpl : angle::NonCopyable
std::vector<sh::Uniform> mUniforms;
std::vector<sh::InterfaceBlock> mInterfaceBlocks;
std::vector<sh::Attribute> mActiveAttributes;
std::vector<sh::Attribute> mActiveOutputVariables;
std::vector<sh::OutputVariable> mActiveOutputVariables;
};
}
......
......@@ -953,10 +953,9 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
}
else
{
const auto &programOutputVars = programData.getOutputVariables();
const auto &shaderOutputVars = fragmentShader->getActiveOutputVariables();
const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
for (auto outputPair : programOutputVars)
for (auto outputPair : programData.getOutputVariables())
{
const VariableLocation &outputLocation = outputPair.second;
const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
......
......@@ -98,15 +98,15 @@ class CollectVariablesTest : public testing::Test
void validateOutputVariableForShader(const std::string &shaderString,
unsigned int varIndex,
const char *varName,
const sh::Attribute **outResult)
const sh::OutputVariable **outResult)
{
const char *shaderStrings[] = {shaderString.c_str()};
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES))
<< mTranslator->getInfoSink().info.str();
const std::vector<sh::Attribute> &outputVariables = mTranslator->getOutputVariables();
const auto &outputVariables = mTranslator->getOutputVariables();
ASSERT_LT(varIndex, outputVariables.size());
const sh::Attribute &outputVariable = outputVariables[varIndex];
const sh::OutputVariable &outputVariable = outputVariables[varIndex];
EXPECT_EQ(-1, outputVariable.location);
EXPECT_TRUE(outputVariable.staticUse);
EXPECT_EQ(varName, outputVariable.name);
......@@ -142,10 +142,10 @@ TEST_F(CollectFragmentVariablesTest, SimpleOutputVar)
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::Attribute> &outputVariables = mTranslator->getOutputVariables();
const auto &outputVariables = mTranslator->getOutputVariables();
ASSERT_EQ(1u, outputVariables.size());
const sh::Attribute &outputVariable = outputVariables[0];
const sh::OutputVariable &outputVariable = outputVariables[0];
EXPECT_EQ(0u, outputVariable.arraySize);
EXPECT_EQ(-1, outputVariable.location);
......@@ -168,10 +168,10 @@ TEST_F(CollectFragmentVariablesTest, LocationOutputVar)
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::Attribute> &outputVariables = mTranslator->getOutputVariables();
const auto &outputVariables = mTranslator->getOutputVariables();
ASSERT_EQ(1u, outputVariables.size());
const sh::Attribute &outputVariable = outputVariables[0];
const sh::OutputVariable &outputVariable = outputVariables[0];
EXPECT_EQ(0u, outputVariable.arraySize);
EXPECT_EQ(5, outputVariable.location);
......@@ -478,7 +478,7 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragColor)
" gl_FragColor = vec4(1.0);\n"
"}\n";
const sh::Attribute *outputVariable = nullptr;
const sh::OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(fragColorShader, 0u, "gl_FragColor", &outputVariable);
ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(0u, outputVariable->arraySize);
......@@ -504,7 +504,7 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragData)
resources.MaxDrawBuffers = kMaxDrawBuffers;
initTranslator(resources);
const sh::Attribute *outputVariable = nullptr;
const sh::OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(fragDataShader, 0u, "gl_FragData", &outputVariable);
ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize);
......@@ -527,7 +527,7 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthMediump)
resources.EXT_frag_depth = 1;
initTranslator(resources);
const sh::Attribute *outputVariable = nullptr;
const sh::OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(fragDepthShader, 0u, "gl_FragDepthEXT", &outputVariable);
ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(0u, outputVariable->arraySize);
......@@ -550,7 +550,7 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthHighp)
resources.FragmentPrecisionHigh = 1;
initTranslator(resources);
const sh::Attribute *outputVariable = nullptr;
const sh::OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(fragDepthHighShader, 0u, "gl_FragDepthEXT", &outputVariable);
ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(0u, outputVariable->arraySize);
......@@ -577,7 +577,7 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary
resources.MaxDualSourceDrawBuffers = resources.MaxDrawBuffers;
initTranslator(resources);
const sh::Attribute *outputVariable = nullptr;
const sh::OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(secondaryFragColorShader, 0u, "gl_FragColor", &outputVariable);
ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(0u, outputVariable->arraySize);
......@@ -615,7 +615,7 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary
resources.MaxDualSourceDrawBuffers = resources.MaxDrawBuffers;
initTranslator(resources);
const sh::Attribute *outputVariable = nullptr;
const sh::OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(secondaryFragDataShader, 0u, "gl_FragData", &outputVariable);
ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize);
......
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