Proper support for fragment output variables for GLSL ES shader version 300.
TRAC #22704
Signed-off-by: Geoff Lang
Signed-off-by: Nicolas Capens
Authored-by: Jamie Madill
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 95bbc29..b36d456 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -156,6 +156,11 @@
return mActiveInterfaceBlocks;
}
+const ActiveShaderVariables &OutputHLSL::getOutputVariables() const
+{
+ return mActiveOutputVariables;
+}
+
int OutputHLSL::vectorSize(const TType &type) const
{
int elementSize = type.isMatrix() ? type.getCols() : 1;
@@ -391,23 +396,44 @@
TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
- const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
-
out << "// Varyings\n";
out << varyings;
- out << "\n"
- "static float4 gl_Color[" << numColorValues << "] =\n"
- "{\n";
- for (unsigned int i = 0; i < numColorValues; i++)
+ out << "\n";
+
+ if (mContext.getShaderVersion() >= 300)
{
- out << " float4(0, 0, 0, 0)";
- if (i + 1 != numColorValues)
+ for (auto outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
{
- out << ",";
+ const TString &variableName = outputVariableIt->first;
+ const TType &variableType = outputVariableIt->second->getType();
+ const TLayoutQualifier &layoutQualifier = variableType.getLayoutQualifier();
+
+ out << "static " + typeString(variableType) + " out_" + variableName + arrayString(variableType) +
+ " = " + initializer(variableType) + ";\n";
+
+ ShaderVariable outputVar(glVariableType(variableType), glVariablePrecision(variableType), variableName.c_str(),
+ (unsigned int)variableType.getArraySize(), layoutQualifier.location);
+ mActiveOutputVariables.push_back(outputVar);
}
- out << "\n";
}
- out << "};\n";
+ else
+ {
+ const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
+
+ out << "static float4 gl_Color[" << numColorValues << "] =\n"
+ "{\n";
+ for (unsigned int i = 0; i < numColorValues; i++)
+ {
+ out << " float4(0, 0, 0, 0)";
+ if (i + 1 != numColorValues)
+ {
+ out << ",";
+ }
+ out << "\n";
+ }
+
+ out << "};\n";
+ }
if (mUsesFragCoord)
{
@@ -1407,7 +1433,12 @@
mReferencedVaryings[name] = node;
out << decorate(name);
}
- else if (qualifier == EvqFragColor || qualifier == EvqFragmentOutput)
+ else if (qualifier == EvqFragmentOutput)
+ {
+ mReferencedOutputVariables[name] = node;
+ out << "out_" << name;
+ }
+ else if (qualifier == EvqFragColor)
{
out << "gl_Color[0]";
mUsesFragColor = true;
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index 0e1ca71..c22ad4f 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -34,6 +34,7 @@
TInfoSinkBase &getBodyStream();
const ActiveUniforms &getUniforms();
const ActiveInterfaceBlocks &getInterfaceBlocks() const;
+ const ActiveShaderVariables &getOutputVariables() const;
TString typeString(const TType &type);
TString textureString(const TType &type);
@@ -88,6 +89,7 @@
ReferencedSymbols mReferencedInterfaceBlocks;
ReferencedSymbols mReferencedAttributes;
ReferencedSymbols mReferencedVaryings;
+ ReferencedSymbols mReferencedOutputVariables;
// Parameters determining what goes in the header output
bool mUsesTexture2D;
@@ -192,6 +194,7 @@
ActiveUniforms mActiveUniforms;
ActiveInterfaceBlocks mActiveInterfaceBlocks;
+ ActiveShaderVariables mActiveOutputVariables;
};
}
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index 31af70d..e49ae7c 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -2028,6 +2028,11 @@
error(location, "", "[", "array indexes for interface blocks arrays must be constant integeral expressions");
recover();
}
+ else if (baseExpression->getQualifier() == EvqFragmentOutput)
+ {
+ error(location, "", "[", "array indexes for output variables must be constant integeral expressions");
+ recover();
+ }
indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
}
diff --git a/src/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index 7b3fa75..07313dd 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -379,6 +379,9 @@
case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY:
*params = (void*)&translator->getInterfaceBlocks();
break;
+ case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY:
+ *params = (void*)&translator->getOutputVariables();
+ break;
default: UNREACHABLE();
}
}
diff --git a/src/compiler/TranslatorHLSL.cpp b/src/compiler/TranslatorHLSL.cpp
index 0819424..6ef91f4 100644
--- a/src/compiler/TranslatorHLSL.cpp
+++ b/src/compiler/TranslatorHLSL.cpp
@@ -22,4 +22,5 @@
outputHLSL.output();
mActiveUniforms = outputHLSL.getUniforms();
mActiveInterfaceBlocks = outputHLSL.getInterfaceBlocks();
+ mActiveOutputVariables = outputHLSL.getOutputVariables();
}
diff --git a/src/compiler/TranslatorHLSL.h b/src/compiler/TranslatorHLSL.h
index 3cb8b90..c031446 100644
--- a/src/compiler/TranslatorHLSL.h
+++ b/src/compiler/TranslatorHLSL.h
@@ -17,12 +17,14 @@
virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; }
const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; }
const sh::ActiveInterfaceBlocks &getInterfaceBlocks() const { return mActiveInterfaceBlocks; }
+ const sh::ActiveShaderVariables &getOutputVariables() { return mActiveOutputVariables; }
protected:
virtual void translate(TIntermNode* root);
sh::ActiveUniforms mActiveUniforms;
sh::ActiveInterfaceBlocks mActiveInterfaceBlocks;
+ sh::ActiveShaderVariables mActiveOutputVariables;
ShShaderOutput mOutputType;
};
diff --git a/src/compiler/Uniform.cpp b/src/compiler/Uniform.cpp
index 8a8b998..602eed5 100644
--- a/src/compiler/Uniform.cpp
+++ b/src/compiler/Uniform.cpp
@@ -11,6 +11,15 @@
namespace sh
{
+ShaderVariable::ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location)
+ : type(type),
+ precision(precision),
+ name(name),
+ arraySize(arraySize),
+ location(location)
+{
+}
+
Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex)
{
this->type = type;
diff --git a/src/compiler/Uniform.h b/src/compiler/Uniform.h
index 22ace9f..e43533a 100644
--- a/src/compiler/Uniform.h
+++ b/src/compiler/Uniform.h
@@ -17,6 +17,19 @@
namespace sh
{
+struct ShaderVariable
+{
+ ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location);
+
+ GLenum type;
+ GLenum precision;
+ std::string name;
+ unsigned int arraySize;
+ int location;
+};
+
+typedef std::vector<ShaderVariable> ActiveShaderVariables;
+
struct Uniform
{
Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex);