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
This commit is contained in:
Jamie Madill 2013-06-20 11:55:50 -04:00 коммит произвёл Shannon Woods
Родитель 05a80cebc3
Коммит 46131a3832
13 изменённых файлов: 180 добавлений и 19 удалений

Просмотреть файл

@ -37,7 +37,7 @@ extern "C" {
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented everytime the API changes. // It is incremented everytime the API changes.
#define ANGLE_SH_VERSION 113 #define ANGLE_SH_VERSION 114
// //
// The names of the following enums have been derived by replacing GL prefix // The names of the following enums have been derived by replacing GL prefix
@ -132,6 +132,7 @@ typedef enum {
SH_ACTIVE_UNIFORMS_ARRAY = 0x6004, SH_ACTIVE_UNIFORMS_ARRAY = 0x6004,
SH_SHADER_VERSION = 0x6005, SH_SHADER_VERSION = 0x6005,
SH_ACTIVE_INTERFACE_BLOCKS_ARRAY = 0x6006, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY = 0x6006,
SH_ACTIVE_OUTPUT_VARIABLES_ARRAY = 0x6007,
} ShShaderInfo; } ShShaderInfo;
// Compile options. // Compile options.

Просмотреть файл

@ -156,6 +156,11 @@ const ActiveInterfaceBlocks &OutputHLSL::getInterfaceBlocks() const
return mActiveInterfaceBlocks; return mActiveInterfaceBlocks;
} }
const ActiveShaderVariables &OutputHLSL::getOutputVariables() const
{
return mActiveOutputVariables;
}
int OutputHLSL::vectorSize(const TType &type) const int OutputHLSL::vectorSize(const TType &type) const
{ {
int elementSize = type.isMatrix() ? type.getCols() : 1; int elementSize = type.isMatrix() ? type.getCols() : 1;
@ -391,12 +396,31 @@ void OutputHLSL::header()
TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); 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 bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
out << "// Varyings\n"; out << "// Varyings\n";
out << varyings; out << varyings;
out << "\n" out << "\n";
"static float4 gl_Color[" << numColorValues << "] =\n"
if (mContext.getShaderVersion() >= 300)
{
for (auto outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
{
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);
}
}
else
{
const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
out << "static float4 gl_Color[" << numColorValues << "] =\n"
"{\n"; "{\n";
for (unsigned int i = 0; i < numColorValues; i++) for (unsigned int i = 0; i < numColorValues; i++)
{ {
@ -407,7 +431,9 @@ void OutputHLSL::header()
} }
out << "\n"; out << "\n";
} }
out << "};\n"; out << "};\n";
}
if (mUsesFragCoord) if (mUsesFragCoord)
{ {
@ -1407,7 +1433,12 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
mReferencedVaryings[name] = node; mReferencedVaryings[name] = node;
out << decorate(name); 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]"; out << "gl_Color[0]";
mUsesFragColor = true; mUsesFragColor = true;

Просмотреть файл

@ -34,6 +34,7 @@ class OutputHLSL : public TIntermTraverser
TInfoSinkBase &getBodyStream(); TInfoSinkBase &getBodyStream();
const ActiveUniforms &getUniforms(); const ActiveUniforms &getUniforms();
const ActiveInterfaceBlocks &getInterfaceBlocks() const; const ActiveInterfaceBlocks &getInterfaceBlocks() const;
const ActiveShaderVariables &getOutputVariables() const;
TString typeString(const TType &type); TString typeString(const TType &type);
TString textureString(const TType &type); TString textureString(const TType &type);
@ -88,6 +89,7 @@ class OutputHLSL : public TIntermTraverser
ReferencedSymbols mReferencedInterfaceBlocks; ReferencedSymbols mReferencedInterfaceBlocks;
ReferencedSymbols mReferencedAttributes; ReferencedSymbols mReferencedAttributes;
ReferencedSymbols mReferencedVaryings; ReferencedSymbols mReferencedVaryings;
ReferencedSymbols mReferencedOutputVariables;
// Parameters determining what goes in the header output // Parameters determining what goes in the header output
bool mUsesTexture2D; bool mUsesTexture2D;
@ -192,6 +194,7 @@ class OutputHLSL : public TIntermTraverser
ActiveUniforms mActiveUniforms; ActiveUniforms mActiveUniforms;
ActiveInterfaceBlocks mActiveInterfaceBlocks; ActiveInterfaceBlocks mActiveInterfaceBlocks;
ActiveShaderVariables mActiveOutputVariables;
}; };
} }

Просмотреть файл

@ -2028,6 +2028,11 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, TS
error(location, "", "[", "array indexes for interface blocks arrays must be constant integeral expressions"); error(location, "", "[", "array indexes for interface blocks arrays must be constant integeral expressions");
recover(); 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); indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
} }

Просмотреть файл

@ -379,6 +379,9 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY: case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY:
*params = (void*)&translator->getInterfaceBlocks(); *params = (void*)&translator->getInterfaceBlocks();
break; break;
case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY:
*params = (void*)&translator->getOutputVariables();
break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }

Просмотреть файл

@ -22,4 +22,5 @@ void TranslatorHLSL::translate(TIntermNode *root)
outputHLSL.output(); outputHLSL.output();
mActiveUniforms = outputHLSL.getUniforms(); mActiveUniforms = outputHLSL.getUniforms();
mActiveInterfaceBlocks = outputHLSL.getInterfaceBlocks(); mActiveInterfaceBlocks = outputHLSL.getInterfaceBlocks();
mActiveOutputVariables = outputHLSL.getOutputVariables();
} }

Просмотреть файл

@ -17,12 +17,14 @@ public:
virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; } virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; }
const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; } const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; }
const sh::ActiveInterfaceBlocks &getInterfaceBlocks() const { return mActiveInterfaceBlocks; } const sh::ActiveInterfaceBlocks &getInterfaceBlocks() const { return mActiveInterfaceBlocks; }
const sh::ActiveShaderVariables &getOutputVariables() { return mActiveOutputVariables; }
protected: protected:
virtual void translate(TIntermNode* root); virtual void translate(TIntermNode* root);
sh::ActiveUniforms mActiveUniforms; sh::ActiveUniforms mActiveUniforms;
sh::ActiveInterfaceBlocks mActiveInterfaceBlocks; sh::ActiveInterfaceBlocks mActiveInterfaceBlocks;
sh::ActiveShaderVariables mActiveOutputVariables;
ShShaderOutput mOutputType; ShShaderOutput mOutputType;
}; };

Просмотреть файл

@ -11,6 +11,15 @@
namespace sh 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) Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex)
{ {
this->type = type; this->type = type;

Просмотреть файл

@ -17,6 +17,19 @@
namespace sh 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 struct Uniform
{ {
Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex); Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex);

Просмотреть файл

@ -41,6 +41,11 @@ std::string arrayString(int i)
return "[" + str(i) + "]"; return "[" + str(i) + "]";
} }
std::string arrayString(unsigned int i)
{
return (i == GL_INVALID_INDEX ? "" : "[" + str(i) + "]");
}
namespace gl_d3d namespace gl_d3d
{ {
std::string TypeString(GLenum type) std::string TypeString(GLenum type)
@ -1055,6 +1060,32 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], F
return registers; return registers;
} }
void ProgramBinary::defineOutputVariables(FragmentShader *fragmentShader)
{
const sh::ActiveShaderVariables &outputVars = fragmentShader->getOutputVariables();
for (unsigned int outputVariableIndex = 0; outputVariableIndex < outputVars.size(); outputVariableIndex++)
{
const sh::ShaderVariable &outputVariable = outputVars[outputVariableIndex];
const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
if (outputVariable.arraySize > 0)
{
for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
{
const int location = baseLocation + elementIndex;
ASSERT(mOutputVariables.count(location) == 0);
mOutputVariables[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
}
}
else
{
ASSERT(mOutputVariables.count(baseLocation) == 0);
mOutputVariables[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
}
}
}
bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4], bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4],
std::string& pixelHLSL, std::string& vertexHLSL, std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader) FragmentShader *fragmentShader, VertexShader *vertexShader)
@ -1355,10 +1386,29 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
"struct PS_OUTPUT\n" "struct PS_OUTPUT\n"
"{\n"; "{\n";
if (mShaderVersion < 300)
{
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{ {
pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n"; pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
} }
}
else
{
defineOutputVariables(fragmentShader);
const sh::ActiveShaderVariables &outputVars = fragmentShader->getOutputVariables();
for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
{
const VariableLocation &outputLocation = locationIt->second;
const sh::ShaderVariable &outputVariable = outputVars[outputLocation.index];
const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : str(outputLocation.element));
pixelHLSL += " " + gl_d3d::TypeString(outputVariable.type) +
" out_" + outputLocation.name + elementString +
" : " + targetSemantic + str(locationIt->first) + ";\n";
}
}
pixelHLSL += "};\n" pixelHLSL += "};\n"
"\n"; "\n";
@ -1473,12 +1523,27 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
"\n" "\n"
" PS_OUTPUT output;\n"; " PS_OUTPUT output;\n";
if (mShaderVersion < 300)
{
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{ {
unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex; unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n"; pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
} }
}
else
{
for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
{
const VariableLocation &outputLocation = locationIt->second;
const std::string &variableName = "out_" + outputLocation.name;
const std::string &outVariableName = variableName + (outputLocation.element == GL_INVALID_INDEX ? "" : str(outputLocation.element));
const std::string &staticVariableName = variableName + arrayString(outputLocation.element);
pixelHLSL += " output." + outVariableName + " = " + staticVariableName + ";\n";
}
}
pixelHLSL += "\n" pixelHLSL += "\n"
" return output;\n" " return output;\n"

Просмотреть файл

@ -164,6 +164,7 @@ class ProgramBinary : public RefCountObject
void defineUniformBlockMembers(const sh::ActiveUniforms &uniforms, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector<unsigned int> *blockUniformIndexes); void defineUniformBlockMembers(const sh::ActiveUniforms &uniforms, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector<unsigned int> *blockUniformIndexes);
bool defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh::InterfaceBlock &interfaceBlock); bool defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh::InterfaceBlock &interfaceBlock);
bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex); bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex);
void defineOutputVariables(FragmentShader *fragmentShader);
std::string generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; std::string generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
std::string generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; std::string generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
@ -206,6 +207,8 @@ class ProgramBinary : public RefCountObject
UniformBlockArray mUniformBlocks; UniformBlockArray mUniformBlocks;
typedef std::vector<VariableLocation> UniformIndex; typedef std::vector<VariableLocation> UniformIndex;
UniformIndex mUniformIndex; UniformIndex mUniformIndex;
typedef std::map<int, VariableLocation> ShaderVariableIndex;
ShaderVariableIndex mOutputVariables;
bool mValidated; bool mValidated;

Просмотреть файл

@ -706,5 +706,26 @@ void FragmentShader::compile()
compileToHLSL(mFragmentCompiler); compileToHLSL(mFragmentCompiler);
parseVaryings(); parseVaryings();
mVaryings.sort(compareVarying); mVaryings.sort(compareVarying);
const char *hlsl = getHLSL();
if (hlsl)
{
void *activeOutputVariables;
ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables);
mActiveOutputVariables = *(sh::ActiveShaderVariables*)activeOutputVariables;
}
} }
void FragmentShader::uncompile()
{
Shader::uncompile();
mActiveOutputVariables.clear();
}
const sh::ActiveShaderVariables &FragmentShader::getOutputVariables() const
{
return mActiveOutputVariables;
}
} }

Просмотреть файл

@ -188,9 +188,13 @@ class FragmentShader : public Shader
virtual GLenum getType(); virtual GLenum getType();
virtual void compile(); virtual void compile();
virtual void uncompile();
const sh::ActiveShaderVariables &getOutputVariables() const;
private: private:
DISALLOW_COPY_AND_ASSIGN(FragmentShader); DISALLOW_COPY_AND_ASSIGN(FragmentShader);
sh::ActiveShaderVariables mActiveOutputVariables;
}; };
} }