Commit 28167c62 by Jamie Madill

Add support for struct varyings, and more robust varying link validation.

TRAC #23749 Signed-off-by: Geoff Lang Signed-off-by: Nicolas Capens
parent 94599669
...@@ -67,5 +67,6 @@ void SafeDeleteArray(T*& resource) ...@@ -67,5 +67,6 @@ void SafeDeleteArray(T*& resource)
#define GL_BGRA4_ANGLEX 0x6ABC #define GL_BGRA4_ANGLEX 0x6ABC
#define GL_BGR5_A1_ANGLEX 0x6ABD #define GL_BGR5_A1_ANGLEX 0x6ABD
#define GL_INT_64_ANGLEX 0x6ABE #define GL_INT_64_ANGLEX 0x6ABE
#define GL_STRUCT_ANGLEX 0x6ABF
#endif // COMMON_ANGLEUTILS_H_ #endif // COMMON_ANGLEUTILS_H_
...@@ -3569,7 +3569,7 @@ void OutputHLSL::declareInterfaceBlockField(const TType &type, const TString &na ...@@ -3569,7 +3569,7 @@ void OutputHLSL::declareInterfaceBlockField(const TType &type, const TString &na
} }
else else
{ {
InterfaceBlockField structField(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), false); InterfaceBlockField structField(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), false);
const TFieldList &fields = structure->fields(); const TFieldList &fields = structure->fields();
...@@ -3603,7 +3603,7 @@ Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &name, ...@@ -3603,7 +3603,7 @@ Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &name,
} }
else else
{ {
Uniform structUniform(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)registerIndex); Uniform structUniform(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)registerIndex);
int fieldRegister = registerIndex; int fieldRegister = registerIndex;
const TFieldList &fields = structure->fields(); const TFieldList &fields = structure->fields();
...@@ -3658,9 +3658,11 @@ void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQual ...@@ -3658,9 +3658,11 @@ void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQual
} }
else else
{ {
Varying structVarying(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), interpolation); Varying structVarying(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), interpolation);
const TFieldList &fields = structure->fields(); const TFieldList &fields = structure->fields();
structVarying.structName = structure->name().c_str();
for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
{ {
const TField &field = *fields[fieldIndex]; const TField &field = *fields[fieldIndex];
......
...@@ -70,6 +70,7 @@ struct Varying : public ShaderVariable ...@@ -70,6 +70,7 @@ struct Varying : public ShaderVariable
std::vector<Varying> fields; std::vector<Varying> fields;
unsigned int registerIndex; // Assigned during link unsigned int registerIndex; // Assigned during link
unsigned int elementIndex; // First register element for varyings, assigned during link unsigned int elementIndex; // First register element for varyings, assigned during link
std::string structName;
Varying(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, InterpolationType interpolationIn); Varying(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, InterpolationType interpolationIn);
......
...@@ -938,19 +938,21 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack ...@@ -938,19 +938,21 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack
{ {
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex]; sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
GLenum transposedType = TransposeMatrixType(varying->type); GLenum transposedType = TransposeMatrixType(varying->type);
int n = VariableRowCount(transposedType) * varying->elementCount();
int m = VariableColumnCount(transposedType); // matrices within varying structs are not transposed
int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
bool success = false; bool success = false;
if (m == 2 || m == 3 || m == 4) if (elements == 2 || elements == 3 || elements == 4)
{ {
for (int r = 0; r <= maxVaryingVectors - n && !success; r++) for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
{ {
bool available = true; bool available = true;
for (int y = 0; y < n && available; y++) for (int y = 0; y < registers && available; y++)
{ {
for (int x = 0; x < m && available; x++) for (int x = 0; x < elements && available; x++)
{ {
if (packing[r + y][x]) if (packing[r + y][x])
{ {
...@@ -964,9 +966,9 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack ...@@ -964,9 +966,9 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack
varying->registerIndex = r; varying->registerIndex = r;
varying->elementIndex = 0; varying->elementIndex = 0;
for (int y = 0; y < n; y++) for (int y = 0; y < registers; y++)
{ {
for (int x = 0; x < m; x++) for (int x = 0; x < elements; x++)
{ {
packing[r + y][x] = &*varying; packing[r + y][x] = &*varying;
} }
...@@ -976,13 +978,13 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack ...@@ -976,13 +978,13 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack
} }
} }
if (!success && m == 2) if (!success && elements == 2)
{ {
for (int r = maxVaryingVectors - n; r >= 0 && !success; r--) for (int r = maxVaryingVectors - registers; r >= 0 && !success; r--)
{ {
bool available = true; bool available = true;
for (int y = 0; y < n && available; y++) for (int y = 0; y < registers && available; y++)
{ {
for (int x = 2; x < 4 && available; x++) for (int x = 2; x < 4 && available; x++)
{ {
...@@ -998,7 +1000,7 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack ...@@ -998,7 +1000,7 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack
varying->registerIndex = r; varying->registerIndex = r;
varying->elementIndex = 2; varying->elementIndex = 2;
for (int y = 0; y < n; y++) for (int y = 0; y < registers; y++)
{ {
for (int x = 2; x < 4; x++) for (int x = 2; x < 4; x++)
{ {
...@@ -1011,7 +1013,7 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack ...@@ -1011,7 +1013,7 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack
} }
} }
} }
else if (m == 1) else if (elements == 1)
{ {
int space[4] = {0}; int space[4] = {0};
...@@ -1027,13 +1029,13 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack ...@@ -1027,13 +1029,13 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack
for (int x = 0; x < 4; x++) for (int x = 0; x < 4; x++)
{ {
if (space[x] >= n && space[x] < space[column]) if (space[x] >= registers && space[x] < space[column])
{ {
column = x; column = x;
} }
} }
if (space[column] >= n) if (space[column] >= registers)
{ {
for (int r = 0; r < maxVaryingVectors; r++) for (int r = 0; r < maxVaryingVectors; r++)
{ {
...@@ -1041,7 +1043,7 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack ...@@ -1041,7 +1043,7 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *pack
{ {
varying->registerIndex = r; varying->registerIndex = r;
for (int y = r; y < r + n; y++) for (int y = r; y < r + registers; y++)
{ {
packing[y][column] = &*varying; packing[y][column] = &*varying;
} }
...@@ -1154,10 +1156,8 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad ...@@ -1154,10 +1156,8 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad
sh::Varying *output = &vertexShader->mVaryings[vertVaryingIndex]; sh::Varying *output = &vertexShader->mVaryings[vertVaryingIndex];
if (output->name == input->name) if (output->name == input->name)
{ {
if (output->type != input->type || output->arraySize != input->arraySize || output->interpolation != input->interpolation) if (!linkValidateVariables(infoLog, output->name, *input, *output))
{ {
infoLog.append("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
return false; return false;
} }
...@@ -1308,7 +1308,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad ...@@ -1308,7 +1308,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad
{ {
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++) for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{ {
int variableRows = VariableRowCount(TransposeMatrixType(varying->type)); int variableRows = (varying->isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying->type)));
for (int row = 0; row < variableRows; row++) for (int row = 0; row < variableRows; row++)
{ {
...@@ -1508,7 +1508,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad ...@@ -1508,7 +1508,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++) for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{ {
GLenum transposedType = TransposeMatrixType(varying->type); GLenum transposedType = TransposeMatrixType(varying->type);
int variableRows = VariableRowCount(transposedType); int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (int row = 0; row < variableRows; row++) for (int row = 0; row < variableRows; row++)
{ {
std::string n = str(varying->registerIndex + elementIndex * variableRows + row); std::string n = str(varying->registerIndex + elementIndex * variableRows + row);
...@@ -1524,6 +1524,12 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad ...@@ -1524,6 +1524,12 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad
pixelHLSL += arrayString(row); pixelHLSL += arrayString(row);
} }
if (varying->isStruct())
{
pixelHLSL += " = input.v" + n + ";\n"; break;
}
else
{
switch (VariableColumnCount(transposedType)) switch (VariableColumnCount(transposedType))
{ {
case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break; case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break;
...@@ -1535,6 +1541,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad ...@@ -1535,6 +1541,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad
} }
} }
} }
}
else UNREACHABLE(); else UNREACHABLE();
} }
...@@ -1589,7 +1596,7 @@ std::string ProgramBinary::generateVaryingHLSL(FragmentShader *fragmentShader, c ...@@ -1589,7 +1596,7 @@ std::string ProgramBinary::generateVaryingHLSL(FragmentShader *fragmentShader, c
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++) for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{ {
GLenum transposedType = TransposeMatrixType(varying->type); GLenum transposedType = TransposeMatrixType(varying->type);
int variableRows = VariableRowCount(transposedType); int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (int row = 0; row < variableRows; row++) for (int row = 0; row < variableRows; row++)
{ {
switch (varying->interpolation) switch (varying->interpolation)
...@@ -1601,7 +1608,10 @@ std::string ProgramBinary::generateVaryingHLSL(FragmentShader *fragmentShader, c ...@@ -1601,7 +1608,10 @@ std::string ProgramBinary::generateVaryingHLSL(FragmentShader *fragmentShader, c
} }
std::string n = str(varying->registerIndex + elementIndex * variableRows + row); std::string n = str(varying->registerIndex + elementIndex * variableRows + row);
std::string typeString = gl_d3d::TypeString(UniformComponentType(transposedType)) + str(VariableColumnCount(transposedType));
// matrices within structs are not transposed, hence we do not use the special struct prefix "rm"
std::string typeString = varying->isStruct() ? "_" + varying->structName :
gl_d3d::TypeString(UniformComponentType(transposedType)) + str(VariableColumnCount(transposedType));
varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n"; varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
} }
...@@ -2153,7 +2163,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at ...@@ -2153,7 +2163,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
return true; return true;
} }
bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable) bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
{ {
if (vertexVariable.type != fragmentVariable.type) if (vertexVariable.type != fragmentVariable.type)
{ {
...@@ -2165,7 +2175,7 @@ bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::strin ...@@ -2165,7 +2175,7 @@ bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::strin
infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str()); infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str());
return false; return false;
} }
if (vertexVariable.precision != fragmentVariable.precision) if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
{ {
infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str()); infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str());
return false; return false;
...@@ -2190,12 +2200,12 @@ bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varN ...@@ -2190,12 +2200,12 @@ bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varN
if (vertexMember.name != fragmentMember.name) if (vertexMember.name != fragmentMember.name)
{ {
infoLog.append("Name mismatch for field %d of %s: (in vertex: '%s', in fragment: '%s')", infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')",
memberIndex, varName.c_str(), vertexVar.name.c_str(), fragmentVar.name.c_str()); memberIndex, varName.c_str(), vertexMember.name.c_str(), fragmentMember.name.c_str());
return false; return false;
} }
const std::string memberName = varName + "." + vertexVar.name; const std::string memberName = varName.substr(0, varName.length()-1) + "." + vertexVar.name + "'";
if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember)) if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember))
{ {
return false; return false;
...@@ -2207,7 +2217,7 @@ bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varN ...@@ -2207,7 +2217,7 @@ bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varN
bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
{ {
if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform)) if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
{ {
return false; return false;
} }
...@@ -2220,9 +2230,30 @@ bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &u ...@@ -2220,9 +2230,30 @@ bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &u
return true; return true;
} }
bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
{
if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
{
return false;
}
if (vertexVarying.interpolation != fragmentVarying.interpolation)
{
infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
return false;
}
if (!linkValidateFields<sh::Varying>(infoLog, varyingName, vertexVarying, fragmentVarying))
{
return false;
}
return true;
}
bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
{ {
if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform)) if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
{ {
return false; return false;
} }
...@@ -2260,7 +2291,7 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform ...@@ -2260,7 +2291,7 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform
if (entry != linkedUniforms.end()) if (entry != linkedUniforms.end())
{ {
const sh::Uniform &vertexUniform = *entry->second; const sh::Uniform &vertexUniform = *entry->second;
const std::string &uniformName = "uniform " + vertexUniform.name; const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform)) if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform))
{ {
return false; return false;
...@@ -2519,12 +2550,12 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter ...@@ -2519,12 +2550,12 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter
if (vertexMember.name != fragmentMember.name) if (vertexMember.name != fragmentMember.name)
{ {
infoLog.append("Name mismatch for field %d of interface block %s: (in vertex: '%s', in fragment: '%s')", infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
return false; return false;
} }
std::string uniformName = "interface block " + vertexInterfaceBlock.name + " member " + vertexMember.name; std::string uniformName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember)) if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember))
{ {
return false; return false;
......
...@@ -159,9 +159,10 @@ class ProgramBinary : public RefCountObject ...@@ -159,9 +159,10 @@ class ProgramBinary : public RefCountObject
template <class ShaderVarType> template <class ShaderVarType>
bool linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar); bool linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar);
bool linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable); bool linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable, bool validatePrecision);
bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
bool linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
bool linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform> &vertexUniforms, const std::vector<sh::Uniform> &fragmentUniforms); bool linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform> &vertexUniforms, const std::vector<sh::Uniform> &fragmentUniforms);
bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog); bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog);
......
...@@ -417,6 +417,12 @@ bool Shader::compareVarying(const sh::ShaderVariable &x, const sh::ShaderVariabl ...@@ -417,6 +417,12 @@ bool Shader::compareVarying(const sh::ShaderVariable &x, const sh::ShaderVariabl
return x.arraySize > y.arraySize; return x.arraySize > y.arraySize;
} }
// Special case for handling structs: we sort these to the end of the list
if (x.type == GL_STRUCT_ANGLEX)
{
return false;
}
unsigned int xPriority = GL_INVALID_INDEX; unsigned int xPriority = GL_INVALID_INDEX;
unsigned int yPriority = GL_INVALID_INDEX; unsigned int yPriority = GL_INVALID_INDEX;
......
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