зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
05a80cebc3
Коммит
46131a3832
|
@ -37,7 +37,7 @@ extern "C" {
|
|||
|
||||
// Version number for shader translation API.
|
||||
// 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
|
||||
|
@ -132,6 +132,7 @@ typedef enum {
|
|||
SH_ACTIVE_UNIFORMS_ARRAY = 0x6004,
|
||||
SH_SHADER_VERSION = 0x6005,
|
||||
SH_ACTIVE_INTERFACE_BLOCKS_ARRAY = 0x6006,
|
||||
SH_ACTIVE_OUTPUT_VARIABLES_ARRAY = 0x6007,
|
||||
} ShShaderInfo;
|
||||
|
||||
// Compile options.
|
||||
|
|
|
@ -156,6 +156,11 @@ const ActiveInterfaceBlocks &OutputHLSL::getInterfaceBlocks() const
|
|||
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 @@ void OutputHLSL::header()
|
|||
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 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
|
|||
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;
|
||||
|
|
|
@ -34,6 +34,7 @@ class OutputHLSL : public TIntermTraverser
|
|||
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 @@ class OutputHLSL : public TIntermTraverser
|
|||
ReferencedSymbols mReferencedInterfaceBlocks;
|
||||
ReferencedSymbols mReferencedAttributes;
|
||||
ReferencedSymbols mReferencedVaryings;
|
||||
ReferencedSymbols mReferencedOutputVariables;
|
||||
|
||||
// Parameters determining what goes in the header output
|
||||
bool mUsesTexture2D;
|
||||
|
@ -192,6 +194,7 @@ class OutputHLSL : public TIntermTraverser
|
|||
|
||||
ActiveUniforms mActiveUniforms;
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -379,6 +379,9 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
|
|||
case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY:
|
||||
*params = (void*)&translator->getInterfaceBlocks();
|
||||
break;
|
||||
case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY:
|
||||
*params = (void*)&translator->getOutputVariables();
|
||||
break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,5 @@ void TranslatorHLSL::translate(TIntermNode *root)
|
|||
outputHLSL.output();
|
||||
mActiveUniforms = outputHLSL.getUniforms();
|
||||
mActiveInterfaceBlocks = outputHLSL.getInterfaceBlocks();
|
||||
mActiveOutputVariables = outputHLSL.getOutputVariables();
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@ public:
|
|||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -41,6 +41,11 @@ std::string arrayString(int i)
|
|||
return "[" + str(i) + "]";
|
||||
}
|
||||
|
||||
std::string arrayString(unsigned int i)
|
||||
{
|
||||
return (i == GL_INVALID_INDEX ? "" : "[" + str(i) + "]");
|
||||
}
|
||||
|
||||
namespace gl_d3d
|
||||
{
|
||||
std::string TypeString(GLenum type)
|
||||
|
@ -1055,6 +1060,32 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], F
|
|||
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],
|
||||
std::string& pixelHLSL, std::string& vertexHLSL,
|
||||
FragmentShader *fragmentShader, VertexShader *vertexShader)
|
||||
|
@ -1355,9 +1386,28 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
|
|||
"struct PS_OUTPUT\n"
|
||||
"{\n";
|
||||
|
||||
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
|
||||
if (mShaderVersion < 300)
|
||||
{
|
||||
pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
|
||||
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
|
||||
{
|
||||
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"
|
||||
|
@ -1473,11 +1523,26 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
|
|||
"\n"
|
||||
" PS_OUTPUT output;\n";
|
||||
|
||||
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
|
||||
if (mShaderVersion < 300)
|
||||
{
|
||||
unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
|
||||
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; 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"
|
||||
|
|
|
@ -164,7 +164,8 @@ class ProgramBinary : public RefCountObject
|
|||
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 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 generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
|
||||
|
||||
|
@ -206,6 +207,8 @@ class ProgramBinary : public RefCountObject
|
|||
UniformBlockArray mUniformBlocks;
|
||||
typedef std::vector<VariableLocation> UniformIndex;
|
||||
UniformIndex mUniformIndex;
|
||||
typedef std::map<int, VariableLocation> ShaderVariableIndex;
|
||||
ShaderVariableIndex mOutputVariables;
|
||||
|
||||
bool mValidated;
|
||||
|
||||
|
|
|
@ -706,5 +706,26 @@ void FragmentShader::compile()
|
|||
compileToHLSL(mFragmentCompiler);
|
||||
parseVaryings();
|
||||
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 void compile();
|
||||
virtual void uncompile();
|
||||
const sh::ActiveShaderVariables &getOutputVariables() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(FragmentShader);
|
||||
|
||||
sh::ActiveShaderVariables mActiveOutputVariables;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче