Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

hand-merge from https://github.com/jims/hlsl2glslfork

Not everything was taken as-is; and right now does not fully work!
  • Loading branch information...
commit 40e2c4a255e37a503857ee4b9387cbd64f6d9fe1 2 parents ed1548d + bc3eecb
@aras-p authored
Showing with 3,047 additions and 3,965 deletions.
  1. +10 −2 README.md
  2. +0 −4 hlslang.vcproj
  3. +0 −6 hlslang.xcodeproj/project.pbxproj
  4. +12 −4 hlslang/GLSLCodeGen/glslCommon.cpp
  5. +3 −1 hlslang/GLSLCodeGen/glslCommon.h
  6. +10 −138 hlslang/GLSLCodeGen/glslFunction.cpp
  7. +15 −18 hlslang/GLSLCodeGen/glslFunction.h
  8. +395 −253 hlslang/GLSLCodeGen/glslOutput.cpp
  9. +6 −3 hlslang/GLSLCodeGen/glslOutput.h
  10. +36 −210 hlslang/GLSLCodeGen/glslSymbol.cpp
  11. +51 −56 hlslang/GLSLCodeGen/glslSymbol.h
  12. +2 −2 hlslang/GLSLCodeGen/hlslCrossCompiler.cpp
  13. +1 −1  hlslang/GLSLCodeGen/hlslCrossCompiler.h
  14. +418 −430 hlslang/GLSLCodeGen/hlslLinker.cpp
  15. +6 −0 hlslang/GLSLCodeGen/hlslLinker.h
  16. +1 −1  hlslang/GLSLCodeGen/hlslSupportLib.cpp
  17. +0 −265 hlslang/Include/ConstantUnion.h
  18. +6 −0 hlslang/Include/PoolAlloc.h
  19. +36 −36 hlslang/Include/Types.h
  20. +393 −323 hlslang/Include/intermediate.h
  21. +8 −3 hlslang/MachineIndependent/HLSL2GLSL.cpp
  22. +9 −3 hlslang/MachineIndependent/Initialize.cpp
  23. +12 −1 hlslang/MachineIndependent/IntermTraverse.cpp
  24. +163 −594 hlslang/MachineIndependent/Intermediate.cpp
  25. +284 −613 hlslang/MachineIndependent/ParseHelper.cpp
  26. +2 −8 hlslang/MachineIndependent/ParseHelper.h
  27. +36 −11 hlslang/MachineIndependent/PoolAlloc.cpp
  28. +1 −1  hlslang/MachineIndependent/RemoveTree.cpp
  29. +10 −10 hlslang/MachineIndependent/SymbolTable.cpp
  30. +144 −156 hlslang/MachineIndependent/SymbolTable.h
  31. +3 −1 hlslang/MachineIndependent/hlslang.l
  32. +364 −405 hlslang/MachineIndependent/hlslang.y
  33. +7 −8 hlslang/MachineIndependent/intermOut.cpp
  34. +33 −29 hlslang/MachineIndependent/localintermediate.h
  35. +0 −251 hlslang/MachineIndependent/parseConst.cpp
  36. +99 −66 include/hlsl2glsl.h
  37. +46 −0 tests/combined/index-matrix-assignment-fragment-out.txt
  38. +46 −0 tests/combined/index-matrix-assignment-fragment-outES.txt
  39. +48 −0 tests/combined/index-matrix-assignment-in.txt
  40. +96 −0 tests/combined/index-matrix-assignment-vertex-out.txt
  41. +96 −0 tests/combined/index-matrix-assignment-vertex-outES.txt
  42. +86 −52 tests/hlsl2glsltest/hlsl2glsltest.cpp
  43. +53 −0 tests/minimal/combined/simple-in.txt
View
12 README.md
@@ -22,6 +22,12 @@ Changes from original HLSL2GLSL 0.9
* Cleaner and more deterministic generated GLSL output
* Unit testing suite
* Simplified interface, code cleanup, unused code removal, merge copy-n-pasted code, simplify implementation etc.
+* Added support for emission of const initializers (including struct and array initializers using GLSL 1.20 array syntax).
+* Removed all constant folding functionality as it was completely broken.
+* A myriad of smaller bug fixes.
+* Support DX10 SV_VertexID, SV_PrimitiveID and SV_InstanceID semantics.
+* Support for shadow sampler types (samplerRECTShadow/sampler2DShadow etc.) which generate appropriate shadow2DRect/shadow2D etc. calls.
+* Fixed unaligned swizzled matrix access & assignments (view._m01_m02_m33 = value)
Notes
@@ -36,6 +42,8 @@ Notes
Status
--------
-Seems to work quite well for Unity's shaders. When/if we bump into any issues; we'll just fix them.
+Used in Unity and bitsquid engine, and seems to work quite ok.
-No optimizations are performed on the generated GLSL, so it is expected that your platform will have a decent GLSL compiler. Or, use [GLSL Optimizer](http://github.com/aras-p/glsl-optimizer), we use it to optimize shaders produced by HLSL2GLSL; gives a substantial performance boost on mobile platforms.
+Support for DX11 features will probably not be added due to the bad condition the original code is in (very obscure and inefficient), instead maybe a new cross-compiler will be made.
+
+No optimizations are performed on the generated GLSL, so it is expected that your platform will have a decent GLSL compiler. Or, use [GLSL Optimizer](http://github.com/aras-p/glsl-optimizer), at Unity we use it to optimize shaders produced by HLSL2GLSL; gives a substantial performance boost on mobile platforms.
View
4 hlslang.vcproj
@@ -461,10 +461,6 @@
>
</File>
<File
- RelativePath="hlslang\MachineIndependent\parseConst.cpp"
- >
- </File>
- <File
RelativePath="hlslang\MachineIndependent\ParseHelper.cpp"
>
</File>
View
6 hlslang.xcodeproj/project.pbxproj
@@ -29,7 +29,6 @@
2B951CB11135197300DBAF46 /* IntermTraverse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AC10E2B0AF106F40045E29C /* IntermTraverse.cpp */; };
2B951CB31135197300DBAF46 /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 3AC10EAA0AF109530045E29C /* memory.c */; };
2B951CB41135197300DBAF46 /* ossource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AC10E480AF107290045E29C /* ossource.cpp */; };
- 2B951CB51135197300DBAF46 /* parseConst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AC10E2C0AF106F40045E29C /* parseConst.cpp */; };
2B951CB61135197300DBAF46 /* ParseHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AC10E2D0AF106F40045E29C /* ParseHelper.cpp */; };
2B951CB71135197300DBAF46 /* PoolAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AC10E2E0AF106F40045E29C /* PoolAlloc.cpp */; };
2B951CB81135197300DBAF46 /* propagateMutable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AC10E060AF103660045E29C /* propagateMutable.cpp */; };
@@ -52,7 +51,6 @@
3A9176410A643D5A00E8641B /* InitializeDll.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InitializeDll.h; sourceTree = "<group>"; };
3AC10DD20AF103020045E29C /* BaseTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = BaseTypes.h; path = hlslang/Include/BaseTypes.h; sourceTree = "<group>"; };
3AC10DD30AF103020045E29C /* Common.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Common.h; path = hlslang/Include/Common.h; sourceTree = "<group>"; };
- 3AC10DD40AF103020045E29C /* ConstantUnion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ConstantUnion.h; path = hlslang/Include/ConstantUnion.h; sourceTree = "<group>"; };
3AC10DD50AF103020045E29C /* InfoSink.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = InfoSink.h; path = hlslang/Include/InfoSink.h; sourceTree = "<group>"; };
3AC10DD60AF103020045E29C /* InitializeGlobals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = InitializeGlobals.h; path = hlslang/Include/InitializeGlobals.h; sourceTree = "<group>"; };
3AC10DD70AF103020045E29C /* InitializeParseContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = InitializeParseContext.h; path = hlslang/Include/InitializeParseContext.h; sourceTree = "<group>"; };
@@ -91,7 +89,6 @@
3AC10E290AF106F40045E29C /* Intermediate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Intermediate.cpp; path = hlslang/MachineIndependent/Intermediate.cpp; sourceTree = "<group>"; };
3AC10E2A0AF106F40045E29C /* intermOut.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = intermOut.cpp; path = hlslang/MachineIndependent/intermOut.cpp; sourceTree = "<group>"; };
3AC10E2B0AF106F40045E29C /* IntermTraverse.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = IntermTraverse.cpp; path = hlslang/MachineIndependent/IntermTraverse.cpp; sourceTree = "<group>"; };
- 3AC10E2C0AF106F40045E29C /* parseConst.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = parseConst.cpp; path = hlslang/MachineIndependent/parseConst.cpp; sourceTree = "<group>"; };
3AC10E2D0AF106F40045E29C /* ParseHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseHelper.cpp; path = hlslang/MachineIndependent/ParseHelper.cpp; sourceTree = "<group>"; };
3AC10E2E0AF106F40045E29C /* PoolAlloc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PoolAlloc.cpp; path = hlslang/MachineIndependent/PoolAlloc.cpp; sourceTree = "<group>"; };
3AC10E300AF106F40045E29C /* RemoveTree.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = RemoveTree.cpp; path = hlslang/MachineIndependent/RemoveTree.cpp; sourceTree = "<group>"; };
@@ -209,7 +206,6 @@
children = (
3AC10DD20AF103020045E29C /* BaseTypes.h */,
3AC10DD30AF103020045E29C /* Common.h */,
- 3AC10DD40AF103020045E29C /* ConstantUnion.h */,
3AC10DD50AF103020045E29C /* InfoSink.h */,
3AC10DD60AF103020045E29C /* InitializeGlobals.h */,
3AC10DD70AF103020045E29C /* InitializeParseContext.h */,
@@ -234,7 +230,6 @@
3AC10E290AF106F40045E29C /* Intermediate.cpp */,
3AC10E2A0AF106F40045E29C /* intermOut.cpp */,
3AC10E2B0AF106F40045E29C /* IntermTraverse.cpp */,
- 3AC10E2C0AF106F40045E29C /* parseConst.cpp */,
3AC10E2D0AF106F40045E29C /* ParseHelper.cpp */,
3AC10E2E0AF106F40045E29C /* PoolAlloc.cpp */,
3AC10E300AF106F40045E29C /* RemoveTree.cpp */,
@@ -417,7 +412,6 @@
2B951CB11135197300DBAF46 /* IntermTraverse.cpp in Sources */,
2B951CB31135197300DBAF46 /* memory.c in Sources */,
2B951CB41135197300DBAF46 /* ossource.cpp in Sources */,
- 2B951CB51135197300DBAF46 /* parseConst.cpp in Sources */,
2B951CB61135197300DBAF46 /* ParseHelper.cpp in Sources */,
2B951CB71135197300DBAF46 /* PoolAlloc.cpp in Sources */,
2B951CB81135197300DBAF46 /* propagateMutable.cpp in Sources */,
View
16 hlslang/GLSLCodeGen/glslCommon.cpp
@@ -26,11 +26,13 @@ const char typeString[EgstTypeCount][32] =
"mat4",
"sampler",
"sampler1D",
+ "sampler1DShadow",
"sampler2D",
+ "sampler2DShadow",
"sampler3D",
"samplerCube",
"sampler2DRect",
- "sampler2DShadow",
+ "sampler2DRectShadow",
"struct"
};
@@ -77,11 +79,13 @@ void writeType (std::stringstream &out, EGlslSymbolType type, GlslStruct *s, TPr
case EgstFloat4x4:
case EgstSamplerGeneric:
case EgstSampler1D:
+ case EgstSampler1DShadow:
case EgstSampler2D:
+ case EgstSampler2DShadow:
case EgstSampler3D:
case EgstSamplerCube:
case EgstSamplerRect:
- case EgstSampler2DShadow:
+ case EgstSamplerRectShadow:
out << typeString[type];
break;
case EgstStruct:
@@ -128,16 +132,20 @@ EGlslSymbolType translateType( const TType *type )
return EgstSamplerGeneric;
case EbtSampler1D:
return EgstSampler1D;
+ case EbtSampler1DShadow:
+ return EgstSampler1DShadow;
case EbtSampler2D:
return EgstSampler2D;
+ case EbtSampler2DShadow:
+ return EgstSampler2DShadow;
case EbtSampler3D:
return EgstSampler3D;
case EbtSamplerCube:
return EgstSamplerCube;
case EbtSamplerRect:
return EgstSamplerRect;
- case EbtSampler2DShadow:
- return EgstSampler2DShadow;
+ case EbtSamplerRectShadow:
+ return EgstSamplerRectShadow;
case EbtStruct:
return EgstStruct;
}
View
4 hlslang/GLSLCodeGen/glslCommon.h
@@ -31,11 +31,13 @@ enum EGlslSymbolType
EgstFloat4x4,
EgstSamplerGeneric,
EgstSampler1D,
+ EgstSampler1DShadow,
EgstSampler2D,
+ EgstSampler2DShadow,
EgstSampler3D,
EgstSamplerCube,
EgstSamplerRect,
- EgstSampler2DShadow,
+ EgstSamplerRectShadow,
EgstStruct,
EgstTypeCount
};
View
148 hlslang/GLSLCodeGen/glslFunction.cpp
@@ -17,15 +17,19 @@ GlslFunction::GlslFunction( const std::string &n, const std::string &m, EGlslSym
depth(0),
inStatement(false)
{
- active.setf ( std::stringstream::showpoint );
- active.unsetf(std::ios::fixed);
- active.unsetf(std::ios::scientific);
- active.precision (6);
+ active = new std::stringstream();
+ active->setf ( std::stringstream::showpoint );
+ active->unsetf(std::ios::fixed);
+ active->unsetf(std::ios::scientific);
+ active->precision (6);
+ pushDepth(0);
}
GlslFunction::~GlslFunction()
{
+ popDepth();
+ delete active;
for (std::vector<GlslSymbol*>::iterator it = symbols.begin(); it < symbols.end(); it++)
{
(*it)->releaseRef ();
@@ -36,6 +40,8 @@ GlslFunction::~GlslFunction()
}
}
+void GlslFunction::pushDepth(int depth) { this->depth.push_back(depth); }
+void GlslFunction::popDepth() { depth.pop_back(); }
bool GlslFunction::hasSymbol( int id )
{
@@ -118,137 +124,3 @@ std::string GlslFunction::getPrototype()
return out.str();
}
-
-std::string GlslFunction::getLocalDecls( int indentLevel )
-{
- std::stringstream out;
- int oldDepth;
-
- // Make sure that decimal points are printed to the output string. Otherwise, the following:
- // float fTemp = 1.0;
- // will come out:
- // float fTemp = 1;
- // causing a GLSL parse error
- out.setf ( std::stringstream::showpoint );
- out.unsetf(std::ios::fixed);
- out.unsetf(std::ios::scientific);
- out.precision (6);
-
- //save off the old depth, to restore later, this is probably unnecessary
- oldDepth = depth;
- depth = indentLevel;
-
- for (std::vector<GlslSymbol*>::iterator it = symbols.begin(); it < symbols.end(); it++)
- {
- if ( (!(*it)->getIsParameter() && !(*it)->getIsGlobal() && !(*it)->getIsMutable()) )
- {
- indent(out);
- if ((*it)->hasInitializer())
- {
- (*it)->writeDecl(out, true, false);
- if ((*it)->isArray())
- {
- out <<";\n";
- for (int ii = 0; ii < (*it)->getArraySize(); ii++)
- {
- indent(out);
- out << (*it)->getName() << "[" << ii << "] = ";
- (*it)->writeInitializer(out,ii);
- if ( (ii+1) != (*it)->getArraySize())
- out << ";\n";
- }
- }
- else
- {
- out << " = ";
- (*it)->writeInitializer(out);
- }
- }
- else
- {
- (*it)->writeDecl(out, true, false);
- }
- out << ";\n";
- }
- }
-
- depth = oldDepth;
-
- return out.str();
-}
-
-
-std::string GlslFunction::getMutableDecls( int indentLevel, std::vector<GlslFunction*>::iterator funcBegin,
- std::vector<GlslFunction*>::iterator funcEnd )
-{
- std::stringstream out;
- int oldDepth;
-
- // Make sure that decimal points are printed to the output string. Otherwise, the following:
- // float fTemp = 1.0;
- // will come out:
- // float fTemp = 1;
- // causing a GLSL parse error
- out.setf ( std::stringstream::showpoint );
- out.precision (6);
-
- //save off the old depth, to restore later, this is probably unnecessary
- oldDepth = depth;
- depth = indentLevel;
-
- for (std::vector<GlslSymbol*>::iterator it = symbols.begin(); it < symbols.end(); it++)
- {
- if ( (*it)->getIsMutable() )
- {
- bool bMutableAlreadyProcessed = false;
-
- // Check the set of already processed functions to see if the mutable was already
- // written out
- std::vector<GlslFunction*>::iterator fit = funcBegin;
- while ( fit != funcEnd && bMutableAlreadyProcessed == false)
- {
- std::vector<GlslSymbol*> funcSymbols = (*fit)->getSymbols();
-
- for (size_t i = 0; i < funcSymbols.size(); i++ )
- {
- if ( (*it)->getName() == funcSymbols[i]->getName() )
- {
- // Symbol found, this mutable has already been processed. Don't do it again.
- bMutableAlreadyProcessed = true;
- break;
- }
- }
- fit++;
- }
-
- if ( bMutableAlreadyProcessed == false )
- {
- indent(out);
- if ((*it)->isArray())
- {
- for (int ii = 0; ii < (*it)->getArraySize(); ii++)
- {
- out << (*it)->getName() << "[" << ii << "] = ";
- out << (*it)->getName(false) << "[" << ii << "]";
- if ( (ii+1) != (*it)->getArraySize())
- {
- out << ";\n";
- indent(out);
- }
- }
- }
- else
- {
- out << (*it)->getName() << " = " << (*it)->getName(false);
- }
-
- out << ";\n";
- }
- }
- }
-
- depth = oldDepth;
-
- return out.str();
-}
-
View
33 hlslang/GLSLCodeGen/glslFunction.h
@@ -27,15 +27,9 @@ class GlslFunction
GlslSymbol& getSymbol( int id );
std::string getPrototype();
- std::string getLocalDecls( int indentLevel );
-
- /// Returns, as a string, the mutable declarations in the function. Takes a set of other functions to
- /// check whether the mutable has already been declared.
- std::string getMutableDecls( int indentLevel, std::vector<GlslFunction*>::iterator funcBegin,
- std::vector<GlslFunction*>::iterator funcEnd );
/// Returns the active scope
- std::string getCode() { return active.str(); }
+ std::string getCode() { return active->str(); }
int getParameterCount() { return (int)parameters.size();}
GlslSymbol* getParameter( int i ) { return parameters[i];}
@@ -48,17 +42,20 @@ class GlslFunction
const std::vector<GlslSymbol*>& getSymbols() { return symbols; }
- void increaseDepth() { depth++; }
- void decreaseDepth() { depth = depth ? depth-1 : depth; }
+ void increaseDepth() { depth.back()++; }
+ void decreaseDepth() { depth.back() = depth.back() ? depth.back()-1 : depth.back(); }
+
+ void pushDepth(int depth);
+ void popDepth();
- void indent( std::stringstream &s ) { for (int ii = 0; ii < depth; ii++) s << " "; }
- void indent() { indent(active); }
+ void indent( std::stringstream &s ) { for (int ii = 0; ii < depth.back(); ii++) s << " "; }
+ void indent() { indent(*active); }
- void beginBlock( bool brace = true) { if (brace) active << "{\n"; increaseDepth(); inStatement = false; }
- void endBlock() { endStatement(); decreaseDepth(); indent(); active << "}\n"; }
+ void beginBlock( bool brace = true) { if (brace) *active << "{\n"; increaseDepth(); inStatement = false; }
+ void endBlock() { endStatement(); decreaseDepth(); indent(); *active << "}\n"; }
void beginStatement() { if (!inStatement) { indent(); inStatement = true;}}
- void endStatement() { if (inStatement) { active << ";\n"; inStatement = false;}}
+ void endStatement() { if (inStatement) { *active << ";\n"; inStatement = false;}}
const std::string &getName() { return name; }
const std::string &getMangledName() { return mangledName; }
@@ -68,8 +65,8 @@ class GlslFunction
const std::string& getSemantic() const { return semantic; }
GlslStruct* getStruct() { return structPtr; }
void setStruct( GlslStruct *s ) { structPtr = s;}
-
- std::stringstream& getActiveOutput () { return active; }
+ void setActiveOutput(std::stringstream* output) { active = output; }
+ std::stringstream& getActiveOutput () { return *active; }
const TSourceLoc& getLine() const { return line; }
protected:
@@ -86,7 +83,7 @@ class GlslFunction
GlslStruct *structPtr;
// Present indent depth
- int depth;
+ std::vector<int> depth;
// These are the symbols referenced
std::vector<GlslSymbol*> symbols;
@@ -101,7 +98,7 @@ class GlslFunction
std::set<TOperator> libFunctions;
// Stores the active output of the function
- std::stringstream active;
+ std::stringstream* active;
bool inStatement;
View
648 hlslang/GLSLCodeGen/glslOutput.cpp
@@ -7,6 +7,20 @@
#include <cstdlib>
+#ifdef _WIN32
+ #define snprintf _snprintf
+#endif
+
+bool isShadowSampler(TBasicType t) {
+ switch (t) {
+ case EbtSampler1DShadow:
+ case EbtSampler2DShadow:
+ case EbtSamplerRectShadow:
+ return true;
+ default:
+ return false;
+ }
+}
int getElements( EGlslSymbolType t )
{
@@ -39,62 +53,60 @@ int getElements( EGlslSymbolType t )
return 0;
}
+TString buildArrayConstructorString(const TType& type) {
+ std::stringstream constructor;
+ constructor << getTypeString(translateType(&type))
+ << '[' << type.getArraySize() << ']';
-void writeConstantConstructor( std::stringstream& out, EGlslSymbolType t, TPrecision prec, constUnion *c, GlslStruct *str = 0 )
-{
- int elementCount = getElements(t);
- bool construct = elementCount > 1 || str != 0;
-
- if (construct)
- {
- writeType (out, t, str, EbpUndefined);
- out << "( ";
- }
-
- if ( str == 0)
- {
- // simple type
- for (int ii = 0; ii<elementCount; ii++, c++)
- {
- if (construct && ii > 0)
- {
- out << ", ";
- }
+ return TString(constructor.str().c_str());
+}
- switch (c->getType())
- {
- case EbtBool:
- out << (c->getBConst() ? "true" : "false");
- break;
- case EbtInt:
- out << c->getIConst();
- break;
- case EbtFloat:
- GlslSymbol::writeFloat(out, c->getFConst());
- break;
- default:
- assert(0);
- }
- }
- }
- else
- {
- // compound type
- for (int ii = 0; ii<str->memberCount(); ii++)
- {
- const GlslStruct::member &m = str->getMember(ii);
- if (construct && ii > 0)
- out << ", ";
+void writeConstantConstructor( std::stringstream& out, EGlslSymbolType t, TPrecision prec, TIntermConstant *c, GlslStruct *structure = 0 )
+{
+ unsigned n_elems = getElements(t);
+ bool construct = n_elems > 1 || structure != 0;
- writeConstantConstructor (out, m.type, m.precision, c);
- }
- }
+ if (construct) {
+ writeType (out, t, structure, EbpUndefined);
+ out << "(";
+ }
+
+ if (structure) {
+ // compound type
+ unsigned n_members = structure->memberCount();
+ for (unsigned i = 0; i != n_members; ++i) {
+ const GlslStruct::member &m = structure->getMember(i);
+ if (construct && i > 0)
+ out << ", ";
+ writeConstantConstructor (out, m.type, m.precision, c);
+ }
+ } else {
+ // simple type
+ unsigned n_constants = c->getCount();
+ for (unsigned i = 0; i != n_elems; ++i) {
+ unsigned v = Min(i, n_constants - 1);
+ if (construct && i > 0)
+ out << ", ";
+
+ switch (c->getBasicType()) {
+ case EbtBool:
+ out << (c->toBool(v) ? "true" : "false");
+ break;
+ case EbtInt:
+ out << c->toInt(v);
+ break;
+ case EbtFloat:
+ GlslSymbol::writeFloat(out, c->toFloat(v));
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
- if (construct)
- {
- out << ")";
- }
+ if (construct)
+ out << ")";
}
@@ -220,9 +232,33 @@ void setupUnaryBuiltInFuncCall( const TString &name, TIntermUnary *node, TString
}
+
void writeTex( const TString &name, TIntermAggregate *node, TGlslOutputTraverser* goit )
{
- writeFuncCall( name, node, goit);
+ TIntermSequence &sequence = node->getSequence();
+ TBasicType sampler_type = (*sequence.begin())->getAsTyped()->getBasicType();
+ TString new_name;
+
+ if (isShadowSampler(sampler_type)) {
+ if (name == "texture2D")
+ new_name = "shadow2D";
+ else if (name == "texture2DProj")
+ new_name = "shadow2DProj";
+ else if (name == "texture1D")
+ new_name = "shadow1D";
+ else if (name == "texture1DProj")
+ new_name = "shadow1DProj";
+ else if (name == "texture2DRect")
+ new_name = "shadow2DRect";
+ else if (name == "texture2DRectProj")
+ new_name = "shadow2DRectProj";
+ else
+ new_name = name;
+ } else {
+ new_name = name;
+ }
+
+ writeFuncCall(new_name, node, goit);
}
static bool SafeEquals(const char* a, const char* b)
@@ -255,69 +291,154 @@ void TGlslOutputTraverser::outputLineDirective (const TSourceLoc& line)
-TGlslOutputTraverser::TGlslOutputTraverser(TInfoSink& i, std::vector<GlslFunction*> &funcList, std::vector<GlslStruct*> &sList, bool usePrecision)
-: infoSink(i)
-, generatingCode(true)
-, functionList(funcList)
-, structList(sList)
-, m_UsePrecision(usePrecision)
+TGlslOutputTraverser::TGlslOutputTraverser(TInfoSink& i, std::vector<GlslFunction*> &funcList, std::vector<GlslStruct*> &sList, TTranslateOptions options) :
+ infoSink(i)
+ , generatingCode(true)
+ , functionList(funcList)
+ , structList(sList)
+ , swizzleAssignTempCounter(0)
+ , m_UsePrecision(options & ETranslateOpUsePrecision)
+ , m_EmitSnowLeopardCompatibleArrayInitializers(options & ETranslateOpEmitSnowLeopardCompatibleArrayInitializers)
{
- m_LastLineOutput.file = NULL;
- m_LastLineOutput.line = -1;
- visitSymbol = traverseSymbol;
- visitConstantUnion = traverseConstantUnion;
- visitBinary = traverseBinary;
- visitUnary = traverseUnary;
- visitSelection = traverseSelection;
- visitAggregate = traverseAggregate;
- visitLoop = traverseLoop;
- visitBranch = traverseBranch;
-
+ m_LastLineOutput.file = NULL;
+ m_LastLineOutput.line = -1;
+ visitSymbol = traverseSymbol;
+ visitConstantUnion = traverseConstantUnion;
+ visitBinary = traverseBinary;
+ visitUnary = traverseUnary;
+ visitSelection = traverseSelection;
+ visitAggregate = traverseAggregate;
+ visitLoop = traverseLoop;
+ visitBranch = traverseBranch;
+ visitDeclaration = traverseDeclaration;
+
TSourceLoc oneSourceLoc;
oneSourceLoc.file=NULL;
oneSourceLoc.line=1;
global = new GlslFunction( "__global__", "__global__", EgstVoid, EbpUndefined, "", oneSourceLoc);
- functionList.push_back(global);
- current = global;
+ functionList.push_back(global);
+ current = global;
+}
+
+
+bool TGlslOutputTraverser::traverseDeclaration(bool preVisit, TIntermDeclaration* decl, TIntermTraverser* it) {
+ TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it);
+ GlslFunction *current = goit->current;
+ std::stringstream& out = current->getActiveOutput();
+ EGlslSymbolType symbol_type = translateType(decl->getTypePointer());
+ TType& type = *decl->getTypePointer();
+
+
+ bool emit_osx10_6_arrays = goit->m_EmitSnowLeopardCompatibleArrayInitializers
+ && decl->containsArrayInitialization();
+
+ if (emit_osx10_6_arrays) {
+ assert(decl->isSingleInitialization() && "Emission of multiple in-line array declarations isn't supported when running in OS X 10.6 compatible mode.");
+
+ current->indent(out);
+ out << "#if defined(OSX_SNOW_LEOPARD)" << std::endl;
+ current->increaseDepth();
+
+ TQualifier q = type.getQualifier();
+ if (q == EvqConst)
+ q = EvqTemporary;
+
+ current->beginStatement();
+ if (q != EvqTemporary && q != EvqGlobal)
+ out << type.getQualifierString() << " ";
+
+ TIntermBinary* assign = decl->getDeclaration()->getAsBinaryNode();
+ TIntermSymbol* sym = assign->getLeft()->getAsSymbolNode();
+ TIntermSequence& init = assign->getRight()->getAsAggregate()->getSequence();
+
+ writeType(out, symbol_type, NULL, goit->m_UsePrecision ? decl->getPrecision() : EbpUndefined);
+ out << "[" << type.getArraySize() << "] " << sym->getSymbol();
+ current->endStatement();
+
+ unsigned n_vals = init.size();
+ for (unsigned i = 0; i != n_vals; ++i) {
+ current->beginStatement();
+ sym->traverse(goit);
+ out << " = ";
+ init[i]->traverse(goit);
+ current->endStatement();
+ }
+
+ current->decreaseDepth();
+ current->indent(out);
+ out << "#else" << std::endl;
+ current->increaseDepth();
+ }
+
+ current->beginStatement();
+
+ if (type.getQualifier() != EvqTemporary && type.getQualifier() != EvqGlobal)
+ out << type.getQualifierString() << " ";
+
+ if (type.getBasicType() == EbtStruct)
+ out << type.getTypeName();
+ else
+ writeType(out, symbol_type, NULL, goit->m_UsePrecision ? decl->getPrecision() : EbpUndefined);
+
+ if (type.isArray())
+ out << "[" << type.getArraySize() << "]";
+
+ out << " ";
+
+ decl->getDeclaration()->traverse(goit);
+
+ current->endStatement();
+
+ if (emit_osx10_6_arrays) {
+ current->decreaseDepth();
+ current->indent(out);
+ out << "#endif" << std::endl;
+ }
+
+ return false;
}
void TGlslOutputTraverser::traverseSymbol(TIntermSymbol *node, TIntermTraverser *it)
{
- TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it);
- GlslFunction *current = goit->current;
- std::stringstream& out = current->getActiveOutput();
-
- current->beginStatement();
+ TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it);
+ GlslFunction *current = goit->current;
+ std::stringstream& out = current->getActiveOutput();
- if ( ! current->hasSymbol( node->getId()))
- {
+ current->beginStatement();
- //check to see if it is a global we can share
- if ( goit->global->hasSymbol( node->getId()))
- {
- current->addSymbol( &goit->global->getSymbol( node->getId()));
- }
- else
- {
- int array = node->getTypePointer()->isArray() ? node->getTypePointer()->getArraySize() : 0;
- const char* semantic = "";
- if (node->getInfo())
- semantic = node->getInfo()->getSemantic().c_str();
- GlslSymbol * sym = new GlslSymbol( node->getSymbol().c_str(), semantic, node->getId(),
- translateType(node->getTypePointer()), goit->m_UsePrecision?node->getPrecision():EbpUndefined, translateQualifier(node->getQualifier()), array);
- current->addSymbol(sym);
- if (sym->getType() == EgstStruct)
- {
- GlslStruct *s = goit->createStructFromType( node->getTypePointer());
- sym->setStruct(s);
- }
- }
- }
+ if ( ! current->hasSymbol( node->getId()))
+ {
+ //check to see if it is a global we can share
+ if ( goit->global->hasSymbol( node->getId()))
+ {
+ current->addSymbol( &goit->global->getSymbol( node->getId()));
+ }
+ else
+ {
+ int array = node->getTypePointer()->isArray() ? node->getTypePointer()->getArraySize() : 0;
+ const char* semantic = "";
+ if (node->getInfo())
+ semantic = node->getInfo()->getSemantic().c_str();
+
+ GlslSymbol * sym = new GlslSymbol( node->getSymbol().c_str(), semantic, node->getId(),
+ translateType(node->getTypePointer()), goit->m_UsePrecision?node->getPrecision():EbpUndefined, translateQualifier(node->getQualifier()), array);
+ sym->setIsGlobal(node->isGlobal());
+
+ current->addSymbol(sym);
+ if (sym->getType() == EgstStruct)
+ {
+ GlslStruct *s = goit->createStructFromType( node->getTypePointer());
+ sym->setStruct(s);
+ }
+ }
+ }
- out << current->getSymbol( node->getId()).getName();
+ // If we're at the global scope, emit the non-mutable names of uniforms.
+ bool globalScope = current == goit->global;
+ out << current->getSymbol(node->getId()).getName(!globalScope);
}
@@ -342,7 +463,7 @@ void TGlslOutputTraverser::traverseParameterSymbol(TIntermSymbol *node, TIntermT
}
-void TGlslOutputTraverser::traverseConstantUnion( TIntermConstantUnion *node, TIntermTraverser *it )
+void TGlslOutputTraverser::traverseConstantUnion( TIntermConstant *node, TIntermTraverser *it )
{
TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it);
GlslFunction *current = goit->current;
@@ -350,7 +471,6 @@ void TGlslOutputTraverser::traverseConstantUnion( TIntermConstantUnion *node, TI
EGlslSymbolType type = translateType( node->getTypePointer());
GlslStruct *str = 0;
- constUnion *c = node->getUnionArrayPointer();
current->beginStatement();
@@ -359,33 +479,31 @@ void TGlslOutputTraverser::traverseConstantUnion( TIntermConstantUnion *node, TI
str = goit->createStructFromType( node->getTypePointer());
}
- writeConstantConstructor (out, type, goit->m_UsePrecision?node->getPrecision():EbpUndefined, c, str);
+ writeConstantConstructor (out, type, goit->m_UsePrecision?node->getPrecision():EbpUndefined, node, str);
}
-void TGlslOutputTraverser::traverseImmediateConstant( TIntermConstantUnion *node, TIntermTraverser *it )
+void TGlslOutputTraverser::traverseImmediateConstant( TIntermConstant *c, TIntermTraverser *it )
{
TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it);
- constUnion *c = node->getUnionArrayPointer();
-
// These are all expected to be length 1
- assert( node->getSize() == 1);
+ assert(c->getSize() == 1);
// Autotype the result
- switch (c[0].getType())
+ switch (c->getBasicType())
{
case EbtBool:
- goit->indexList.push_back( c[0].getBConst() ? 1 : 0);
+ goit->indexList.push_back(c->toBool() ? 1 : 0);
break;
case EbtInt:
- goit->indexList.push_back( c[0].getIConst());
+ goit->indexList.push_back(c->toInt());
break;
case EbtFloat:
- goit->indexList.push_back( int(c[0].getFConst()));
+ goit->indexList.push_back((int)c->toFloat());
break;
default:
- assert(0);
+ assert(false && "Invalid constant type. Only bool, int and float supported");
goit->indexList.push_back(0);
}
}
@@ -429,49 +547,6 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
switch (node->getOp())
{
case EOpAssign: op = "="; infix = true; needsParens = false; break;
-
- case EOpInitialize:
- if (goit->parseInitializer(node))
- return false;
-
- // Check to see if we have an array initializer list
- if ( node->getLeft() && node->getRight() )
- {
- TIntermSymbol *symNode = node->getLeft()->getAsSymbolNode();
- TIntermAggregate *aggNode = node->getRight()->getAsAggregate();
-
- // Left hand size is a symbol, right hand side is an aggregate. This
- // is an initializer sequence for an array.
- if ( symNode && symNode->isArray() && aggNode )
- {
- // Get the number of elements in the array. TParseContext::constructArray should
- // have already made sure that the correct number of elements are present in
- // the initializer sequence
- int nElements = symNode->getTypePointer()->getArraySize();
-
- // Loop over all elements
- for ( int i = 0; i < nElements; i++ )
- {
- // Initialize each element
- node->getLeft()->traverse(goit);
- out << "[" << i << "] = ";
- aggNode->getSequence()[i]->traverse(goit);
-
- current->endStatement();
- if ( i != nElements - 1 )
- current->beginStatement();
- }
- return false;
- }
- }
-
- // Fallthrough and process as a normal assignment
- current->beginStatement();
- op = "=";
- infix = true;
- needsParens = false;
- break;
-
case EOpAddAssign: op = "+="; infix = true; needsParens = false; break;
case EOpSubAssign: op = "-="; infix = true; needsParens = false; break;
case EOpMulAssign: op = "*="; infix = true; needsParens = false; break;
@@ -500,7 +575,7 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
if (left->isMatrix() && !left->isArray())
{
- if (right->getAsConstantUnion())
+ if (right->getAsConstant())
{
current->addLibFunction (EOpMatrixIndex);
out << "xll_matrixindex (";
@@ -527,7 +602,7 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
left->traverse(goit);
// Special code for handling a vector component select (this improves readability)
- if (left->isVector() && !left->isArray() && right->getAsConstantUnion())
+ if (left->isVector() && !left->isArray() && right->getAsConstant())
{
char swiz[] = "xyzw";
goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant;
@@ -559,7 +634,7 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
if (left && right && left->isMatrix() && !left->isArray())
{
- if (right->getAsConstantUnion())
+ if (right->getAsConstant())
{
current->addLibFunction (EOpMatrixIndex);
out << "xll_matrixindex (";
@@ -644,67 +719,74 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
goit->generatingCode = true;
return false;
- case EOpMatrixSwizzle:
- current->beginStatement();
- // This presently only works for swizzles as rhs operators
- goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant;
- goit->generatingCode = false;
- if (node->getRight())
- {
- node->getRight()->traverse(goit);
- assert( goit->indexList.size() <= 4);
- assert( goit->indexList.size() > 0);
- int collumn[4], row[4];
- for (int ii = 0; ii < (int)goit->indexList.size(); ii++)
- {
- int val = goit->indexList[ii];
- collumn[ii] = val/4;
- row[ii] = val%4;
- }
- bool sameCollumn = true;
- for (int ii = 1; ii < (int)goit->indexList.size(); ii++)
- {
- sameCollumn &= collumn[ii] == collumn[ii-1];
- }
- if (sameCollumn)
- {
- //select column, then swizzle row
- if (node->getLeft())
- node->getLeft()->traverse(goit);
- out << "[" << collumn[0] << "].";
- const char fields[] = "xyzw";
- for (int ii = 0; ii < (int)goit->indexList.size(); ii++)
- {
- out << fields[row[ii]];
- }
- }
- else
- {
- // Insert constructor, and dereference individually
-
- // Might need to account for different types here
- assert( (int)goit->indexList.size() != 1); //should have hit same collumn case
- out << "vec" << (int)goit->indexList.size() << "( ";
- const char fields[] = "xyzw";
- if (node->getLeft())
- node->getLeft()->traverse(goit);
- out << "[" << collumn[0] << "].";
- out << fields[row[0]];
- for (int ii = 1; ii < (int)goit->indexList.size(); ii++)
- {
- out << ", ";
- if (node->getLeft())
- node->getLeft()->traverse(goit);
- out << "[" << collumn[ii] << "].";
- out << fields[row[ii]];
- }
- out << ")";
- }
- }
- goit->indexList.clear();
- goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion;
- goit->generatingCode = true;
- return false;
+ case EOpMatrixSwizzle:
+ // This presently only works for swizzles as rhs operators
+ if (node->getRight())
+ {
+ goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant;
+ goit->generatingCode = false;
+
+ node->getRight()->traverse(goit);
+
+ goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion;
+ goit->generatingCode = true;
+
+ std::vector<int> elements = goit->indexList;
+ goit->indexList.clear();
+
+ if (elements.size() > 4 || elements.size() < 1) {
+ goit->infoSink.info << "Matrix swizzle operations can must contain at least 1 and at most 4 element selectors.";
+ return true;
+ }
+
+ unsigned column[4] = {0}, row[4] = {0};
+ for (unsigned i = 0; i != elements.size(); ++i)
+ {
+ unsigned val = elements[i];
+ column[i] = val % 4;
+ row[i] = val / 4;
+ }
+
+ bool sameColumn = true;
+ for (unsigned i = 1; i != elements.size(); ++i)
+ sameColumn &= column[i] == column[i-1];
+
+ static const char* fields = "xyzw";
+
+ if (sameColumn)
+ {
+ //select column, then swizzle row
+ if (node->getLeft())
+ node->getLeft()->traverse(goit);
+ out << "[" << column[0] << "].";
+
+ for (unsigned i = 0; i < elements.size(); ++i)
+ out << fields[row[i]];
+ }
+ else
+ {
+ // Insert constructor, and dereference individually
+
+ // Might need to account for different types here
+ assert( elements.size() != 1); //should have hit same collumn case
+ out << "vec" << elements.size() << "(";
+ if (node->getLeft())
+ node->getLeft()->traverse(goit);
+ out << "[" << column[0] << "].";
+ out << fields[row[0]];
+
+ for (unsigned i = 1; i < elements.size(); ++i)
+ {
+ out << ", ";
+ if (node->getLeft())
+ node->getLeft()->traverse(goit);
+ out << "[" << column[i] << "].";
+ out << fields[row[i]];
+ }
+ out << ")";
+ }
+ }
+ return false;
case EOpAdd: op = "+"; infix = true; break;
case EOpSub: op = "-"; infix = true; break;
@@ -758,6 +840,57 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
if (infix)
{
+ // special case for swizzled matrix assignment
+ if (node->getOp() == EOpAssign && node->getLeft() && node->getRight()) {
+ TIntermBinary* lval = node->getLeft()->getAsBinaryNode();
+
+ if (lval && lval->getOp() == EOpMatrixSwizzle) {
+ static const char* vec_swizzles = "xyzw";
+ TIntermTyped* rval = node->getRight();
+ TIntermTyped* lexp = lval->getLeft();
+
+ goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant;
+ goit->generatingCode = false;
+
+ lval->getRight()->traverse(goit);
+
+ goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion;
+ goit->generatingCode = true;
+
+ std::vector<int> swizzles = goit->indexList;
+ goit->indexList.clear();
+
+ char temp_rval[128];
+ unsigned n_swizzles = swizzles.size();
+
+ if (n_swizzles > 1) {
+ snprintf(temp_rval, 128, "xlat_swiztemp%d", goit->swizzleAssignTempCounter++);
+
+ current->beginStatement();
+ out << "vec" << n_swizzles << " " << temp_rval << " = ";
+ rval->traverse(goit);
+ current->endStatement();
+ }
+
+ for (unsigned i = 0; i != n_swizzles; ++i) {
+ unsigned col = swizzles[i] / 4;
+ unsigned row = swizzles[i] % 4;
+
+ current->beginStatement();
+ lexp->traverse(goit);
+ out << "[" << row << "][" << col << "] = ";
+ if (n_swizzles > 1)
+ out << temp_rval << "." << vec_swizzles[i];
+ else
+ rval->traverse(goit);
+
+ current->endStatement();
+ }
+
+ return false;
+ }
+ }
+
if (needsParens)
out << '(';
@@ -773,7 +906,7 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
else
{
if (assign)
- {
+ {
// Need to traverse the left child twice to allow for the assign and the op
// This is OK, because we know it is an lvalue
if (node->getLeft())
@@ -1146,12 +1279,11 @@ bool TGlslOutputTraverser::traverseAggregate( bool preVisit, TIntermAggregate *n
case EOpConstructIVec2: writeFuncCall( "ivec2", node, goit); return false;
case EOpConstructIVec3: writeFuncCall( "ivec3", node, goit); return false;
case EOpConstructIVec4: writeFuncCall( "ivec4", node, goit); return false;
+
case EOpConstructMat2: writeFuncCall( "mat2", node, goit); return false;
case EOpConstructMat3: writeFuncCall( "mat3", node, goit); return false;
case EOpConstructMat4: writeFuncCall( "mat4", node, goit); return false;
- case EOpConstructStruct: writeFuncCall( "struct", node, goit); return false;
-
-
+
case EOpConstructMat2FromMat:
current->addLibFunction(EOpConstructMat2FromMat);
writeFuncCall( "xll_constructMat2", node, goit);
@@ -1161,6 +1293,9 @@ bool TGlslOutputTraverser::traverseAggregate( bool preVisit, TIntermAggregate *n
current->addLibFunction(EOpConstructMat3FromMat);
writeFuncCall( "xll_constructMat3", node, goit);
return false;
+
+ case EOpConstructStruct: writeFuncCall( node->getTypePointer()->getTypeName(), node, goit); return false;
+ case EOpConstructArray: writeFuncCall( buildArrayConstructorString(*node->getTypePointer()), node, goit); return false;
case EOpComma:
{
@@ -1265,7 +1400,7 @@ bool TGlslOutputTraverser::traverseAggregate( bool preVisit, TIntermAggregate *n
return false;
case EOpTex2DProj:
- writeTex( "texture2DProj", node, goit);
+ writeTex( "texture2DProj", node, goit);
return false;
case EOpTex2DLod:
@@ -1411,30 +1546,30 @@ bool TGlslOutputTraverser::traverseLoop( bool preVisit, TIntermLoop *node, TInte
current->endBlock();
}
else if (loopType == ELoopWhile)
- {
- // Process while loop
- out << "while ( ";
+ {
+ // Process while loop
+ out << "while ( ";
node->getCondition()->traverse(goit);
- out << " ) ";
- current->beginBlock();
- if (node->getBody())
- node->getBody()->traverse(goit);
- current->endBlock();
- }
- else
- {
+ out << " ) ";
+ current->beginBlock();
+ if (node->getBody())
+ node->getBody()->traverse(goit);
+ current->endBlock();
+ }
+ else
+ {
assert(loopType == ELoopDoWhile);
- // Process do loop
- out << "do ";
- current->beginBlock();
- if (node->getBody())
- node->getBody()->traverse(goit);
- current->endBlock();
- current->indent();
- out << "while ( ";
+ // Process do loop
+ out << "do ";
+ current->beginBlock();
+ if (node->getBody())
+ node->getBody()->traverse(goit);
+ current->endBlock();
+ current->indent();
+ out << "while ( ";
node->getCondition()->traverse(goit);
- out << " )\n";
- }
+ out << " )\n";
+ }
return false;
}
@@ -1538,14 +1673,11 @@ bool TGlslOutputTraverser::parseInitializer( TIntermBinary *node )
left = node->getLeft();
right = node->getRight();
- if (! left->getAsSymbolNode())
+ if (!left->getAsSymbolNode())
return false; //Something is likely seriously wrong
- if (! right->getAsConstantUnion())
- return false; //only constant initializers
-
TIntermSymbol *symNode = left->getAsSymbolNode();
- TIntermConstantUnion *cUnion = right->getAsConstantUnion();
+
if (symNode->getBasicType() == EbtStruct)
return false;
@@ -1567,9 +1699,19 @@ bool TGlslOutputTraverser::parseInitializer( TIntermBinary *node )
}
else
return false; //can't init already declared variable
-
-
- sym->setInitializer ( cUnion->getUnionArrayPointer() );
+
+ if (right->getAsTyped())
+ {
+ std::stringstream ss;
+ std::stringstream* oldOut = &current->getActiveOutput();
+ current->pushDepth(0);
+ current->setActiveOutput(&ss);
+ right->getAsTyped()->traverse(this);
+ current->setActiveOutput(oldOut);
+ current->popDepth();
+
+ sym->setInitializer(ss.str());
+ }
return true;
}
View
9 hlslang/GLSLCodeGen/glslOutput.h
@@ -20,19 +20,20 @@ class TGlslOutputTraverser : public TIntermTraverser
private:
static void traverseSymbol(TIntermSymbol*, TIntermTraverser*);
static void traverseParameterSymbol(TIntermSymbol *node, TIntermTraverser *it);
- static void traverseConstantUnion(TIntermConstantUnion*, TIntermTraverser*);
- static void traverseImmediateConstant( TIntermConstantUnion *node, TIntermTraverser *it);
+ static void traverseConstantUnion(TIntermConstant*, TIntermTraverser*);
+ static void traverseImmediateConstant( TIntermConstant *node, TIntermTraverser *it);
static bool traverseBinary(bool preVisit, TIntermBinary*, TIntermTraverser*);
static bool traverseUnary(bool preVisit, TIntermUnary*, TIntermTraverser*);
static bool traverseSelection(bool preVisit, TIntermSelection*, TIntermTraverser*);
static bool traverseAggregate(bool preVisit, TIntermAggregate*, TIntermTraverser*);
static bool traverseLoop(bool preVisit, TIntermLoop*, TIntermTraverser*);
static bool traverseBranch(bool preVisit, TIntermBranch*, TIntermTraverser*);
+ static bool traverseDeclaration(bool preVisit, TIntermDeclaration*, TIntermTraverser*);
void outputLineDirective (const TSourceLoc& line);
public:
- TGlslOutputTraverser (TInfoSink& i, std::vector<GlslFunction*> &funcList, std::vector<GlslStruct*> &sList, bool usePrecision);
+ TGlslOutputTraverser (TInfoSink& i, std::vector<GlslFunction*> &funcList, std::vector<GlslStruct*> &sList, TTranslateOptions options);
GlslStruct *createStructFromType( TType *type );
bool parseInitializer( TIntermBinary *node );
@@ -60,7 +61,9 @@ class TGlslOutputTraverser : public TIntermTraverser
// Persistent data for collecting indices
std::vector<int> indexList;
+ unsigned swizzleAssignTempCounter;
bool m_UsePrecision;
+ bool m_EmitSnowLeopardCompatibleArrayInitializers;
TSourceLoc m_LastLineOutput;
};
View
246 hlslang/GLSLCodeGen/glslSymbol.cpp
@@ -5,6 +5,7 @@
#include "glslSymbol.h"
+#include <float.h>
static void writeBool( std::stringstream &out, bool b )
{
@@ -42,8 +43,7 @@ GlslSymbol::GlslSymbol( const std::string &n, const std::string &s, int id, EGls
GlslSymbol::~GlslSymbol()
{
-}
-
+}
bool GlslSymbol::isReservedGlslKeyword ( const std::string &name ) const
{
@@ -60,212 +60,38 @@ bool GlslSymbol::isReservedGlslKeyword ( const std::string &name ) const
void GlslSymbol::writeDecl (std::stringstream &out, bool local, bool skipUniform)
{
- switch (qual)
- {
- case EqtNone: break;
- case EqtUniform:
- if (!skipUniform)
- out << "uniform ";
- break;
- case EqtMutableUniform:
- if (!local)
- out << "uniform ";
- break;
- case EqtConst: out << "const "; break;
- case EqtIn: out << "in "; break;
- case EqtOut: out << "out "; break;
- case EqtInOut: out << "inout "; break;
- }
-
- writeType (out, type, structPtr, precision);
+ switch (qual)
+ {
+ case EqtNone: break;
+ case EqtUniform:
+ if (!skipUniform)
+ out << "uniform ";
+ break;
+ case EqtMutableUniform:
+ if (!local)
+ out << "uniform ";
+ break;
+ case EqtConst: out << "const "; break;
+ case EqtIn: out << "in "; break;
+ case EqtOut: out << "out "; break;
+ case EqtInOut: out << "inout "; break;
+ }
+
+ writeType (out, type, structPtr, precision);
+
+ out << " " << (local ? mutableMangledName : mangledName);
+ if (arraySize)
+ out << "[" << arraySize << "]";
+
+ if (local && qual == EqtMutableUniform)
+ out << " = " << mangledName;
- out << " ";
-
- if (local)
- out << mutableMangledName;
- else
- out << mangledName;
-
- if (arraySize)
- {
- out << "[" << arraySize << "]";
- }
}
void GlslSymbol::writeInitializer( std::stringstream &out, int element )
{
- int elementCount = 0;
- EGlslSymbolType baseType = EgstVoid;
-
- switch (type)
- {
- case EgstBool:
- case EgstBool2:
- case EgstBool3:
- case EgstBool4:
- baseType = EgstBool;
- elementCount = type - EgstBool + 1;
- break;
-
- case EgstInt:
- case EgstInt2:
- case EgstInt3:
- case EgstInt4:
- baseType = EgstInt;
- elementCount = type - EgstInt + 1;
- break;
-
- case EgstFloat:
- case EgstFloat2:
- case EgstFloat3:
- case EgstFloat4:
- baseType = EgstFloat;
- elementCount = type - EgstFloat + 1;
- break;
-
- case EgstFloat2x2:
- case EgstFloat3x3:
- case EgstFloat4x4:
- baseType = EgstFloat;
- elementCount = type - EgstFloat2x2 + 2;
- elementCount *= elementCount;
- break;
-
- default:
- assert(0);
- }
-
- int offset = elementCount * element;
-
- if (baseType == EgstBool)
- {
- if (elementCount > 1)
- out << getTypeString(type) << '(';
-
- for (int ii = 0; ii < elementCount; ii++)
- {
- if (ii != 0) out << ", ";
- writeBool( out, initializer[ ii + offset] != 0.0f);
- }
-
- if (elementCount > 1)
- out << ')';
- }
- else if (baseType == EgstInt)
- {
- if (elementCount > 1)
- out << getTypeString(type) << '(';
-
- for (int ii = 0; ii < elementCount; ii++)
- {
- if (ii != 0) out << ", ";
- out << (int)initializer[ ii + offset];
- }
-
- if (elementCount > 1)
- out << ')';
- }
- else if (baseType == EgstFloat)
- {
- if (elementCount > 1)
- out << getTypeString(type) << '(';
-
- for (int ii = 0; ii < elementCount; ii++)
- {
- if (ii != 0) out << ", ";
- writeFloat(out, initializer[ ii + offset]);
- }
-
- if (elementCount > 1)
- out << ')';
- }
- else
- {
- assert(0);
- }
-}
-
-
-void GlslSymbol::setInitializer( const constUnion *ptr )
-{
- int elementCount = 0;
- EGlslSymbolType baseType = EgstVoid;
- int as = arraySize;
-
- as = (as) ? as : 1;
-
- // No support for initialization of samplers or structures presently
- assert( type < EgstSamplerGeneric);
-
- initializer.clear();
-
- switch (type)
- {
- case EgstBool:
- case EgstBool2:
- case EgstBool3:
- case EgstBool4:
- baseType = EgstBool;
- elementCount = type - EgstBool + 1;
- break;
-
- case EgstInt:
- case EgstInt2:
- case EgstInt3:
- case EgstInt4:
- baseType = EgstInt;
- elementCount = type - EgstInt + 1;
- break;
-
- case EgstFloat:
- case EgstFloat2:
- case EgstFloat3:
- case EgstFloat4:
- baseType = EgstFloat;
- elementCount = type - EgstFloat + 1;
- break;
-
- case EgstFloat2x2:
- case EgstFloat3x3:
- case EgstFloat4x4:
- baseType = EgstFloat;
- elementCount = type - EgstFloat2x2 + 2;
- elementCount *= elementCount; //square it
- break;
-
- default:
- assert(0);
- }
-
- // Handle the all the array elements
- elementCount *= as;
-
- if (baseType == EgstBool)
- {
- for (int ii = 0; ii < elementCount; ii++)
- {
- initializer.push_back( ptr[ii].getBConst() ? 1.0f : 0.0f);
- }
- }
- else if (baseType == EgstInt)
- {
- for (int ii = 0; ii < elementCount; ii++)
- {
- initializer.push_back( (float)ptr[ii].getIConst());
- }
- }
- else if (baseType == EgstFloat)
- {
- for (int ii = 0; ii < elementCount; ii++)
- {
- initializer.push_back( ptr[ii].getFConst());
- }
- }
- else
- {
- assert(0);
- }
+ out << initializerString;
}
// two requirements here:
@@ -280,14 +106,14 @@ void GlslSymbol::setInitializer( const constUnion *ptr )
void GlslSymbol::writeFloat(std::stringstream &out, float f)
{
- char buffer[64];
- sprintf(buffer, "%g", f);
- out << buffer;
-
- if(!strchr(buffer, '.') && !strrchr(buffer, 'e') && !strrchr(buffer, 'E'))
- {
- out << ".0";
- }
+ static char buffer[64];
+
+ if (fractionalPart(f) == 0.f)
+ sprintf(buffer, "%.1f", f);
+ else
+ sprintf(buffer, "%.*g", FLT_DIG, f);
+
+ out << buffer;
}
void GlslSymbol::mangleName()
View
107 hlslang/GLSLCodeGen/glslSymbol.h
@@ -13,76 +13,71 @@
class GlslSymbol
{
public:
+ GlslSymbol( const std::string &n, const std::string &s, int id, EGlslSymbolType t, TPrecision precision, EGlslQualifier q, int as = 0 );
+ virtual ~GlslSymbol();
- GlslSymbol( const std::string &n, const std::string &s, int id, EGlslSymbolType t, TPrecision precision, EGlslQualifier q, int as = 0 );
- virtual ~GlslSymbol();
-
- bool getIsParameter() const { return isParameter; }
+ bool getIsParameter() const { return isParameter; }
+ void setIsParameter( bool param ) { isParameter = param; }
+
+ bool getIsGlobal() const { return isGlobal || qual == EqtUniform || qual == EqtMutableUniform; }
+ void setIsGlobal(bool global) { isGlobal = global; }
- void setIsParameter( bool param ) { isParameter = param; }
-
- bool getIsGlobal() const { return qual == EqtUniform || qual == EqtMutableUniform; }
-
- bool getIsMutable() const { return qual == EqtMutableUniform; }
+ bool getIsMutable() const { return qual == EqtMutableUniform; }
- /// Get mangled name
- const std::string &getName( bool local = true ) const { return ( (local ) ? mutableMangledName : mangledName ); }
-
- bool hasSemantic() const { return (semantic.size() > 0); }
- const std::string &getSemantic() const { return semantic; }
-
- int getId() const { return identifier; }
-
- bool isArray() const { return (arraySize > 0); }
- int getArraySize() const { return arraySize; }
+ /// Get mangled name
+ const std::string &getName( bool local = true ) const { return ( (local ) ? mutableMangledName : mangledName ); }
- EGlslSymbolType getType() const { return type; }
- EGlslQualifier getQualifier() const { return qual; }
- TPrecision getPrecision() const { return precision; }
-
- void updateType( EGlslSymbolType t ) { assert( type == EgstSamplerGeneric); type = t; }
+ bool hasSemantic() const { return (semantic.size() > 0); }
+ const std::string &getSemantic() const { return semantic; }
+
+ int getId() const { return identifier; }
- const GlslStruct* getStruct() const { return structPtr; }
- GlslStruct* getStruct() { return structPtr; }
- void setStruct( GlslStruct *s ) { structPtr = s; }
+ bool isArray() const { return (arraySize > 0); }
+ int getArraySize() const { return arraySize; }
- bool hasInitializer() const { return initializer.size() != 0; }
- const float* getInitializer() const { return &initializer[0]; }
- int initializerSize() const { return (int)initializer.size(); }
+ EGlslSymbolType getType() const { return type; }
+ EGlslQualifier getQualifier() const { return qual; }
+ TPrecision getPrecision() const { return precision; }
- void writeDecl( std::stringstream &out, bool local, bool skipUniform );
- void writeInitializer( std::stringstream &out, int element = 0);
+ void updateType( EGlslSymbolType t ) { assert( type == EgstSamplerGeneric); type = t; }
- void setInitializer( const constUnion *ptr );
+ const GlslStruct* getStruct() const { return structPtr; }
+ GlslStruct* getStruct() { return structPtr; }
+ void setStruct( GlslStruct *s ) { structPtr = s; }
+ void setInitializer(const std::string& str) { initializerString = str; }
+ const std::string& initializer() const { return initializerString; }
- /// Set the mangled name for the symbol
- void mangleName();
+ void writeDecl( std::stringstream &out, bool local, bool skipUniform );
+ void writeInitializer( std::stringstream &out, int element = 0);
+ /// Set the mangled name for the symbol
+ void mangleName();
- void addRef() { refCount++; }
- void releaseRef() { assert (refCount >= 0 ); if ( refCount > 0 ) refCount--; }
- int getRef() const { return refCount; }
+ void addRef() { refCount++; }
+ void releaseRef() { assert (refCount >= 0 ); if ( refCount > 0 ) refCount--; }
+ int getRef() const { return refCount; }
- static void writeFloat(std::stringstream &out, float f);
+ static void writeFloat(std::stringstream &out, float f);
private:
- /// Is the variable name a reserved GLSL keyword that could have passed through the lexer?
- bool isReservedGlslKeyword ( const std::string &name ) const;
-
- std::string name;
- std::string mangledName;
- std::string mutableMangledName;
- std::string semantic;
- int identifier;
- EGlslSymbolType type;
- EGlslQualifier qual;
- TPrecision precision;
- int arraySize;
- int mangle;
- GlslStruct *structPtr;
- bool isParameter;
- std::vector<float> initializer;
- int refCount;
+ /// Is the variable name a reserved GLSL keyword that could have passed through the lexer?
+ bool isReservedGlslKeyword ( const std::string &name ) const;
+
+ std::string name;
+ std::string mangledName;
+ std::string mutableMangledName;
+ std::string semantic;
+ std::string initializerString;
+ int identifier;
+ EGlslSymbolType type;
+ EGlslQualifier qual;
+ TPrecision precision;
+ int arraySize;
+ int mangle;
+ GlslStruct *structPtr;
+ bool isParameter;
+ int refCount;
+ bool isGlobal;
};
#endif //GLSL_SYMBOL_H
View
4 hlslang/GLSLCodeGen/hlslCrossCompiler.cpp
@@ -40,9 +40,9 @@ void HlslCrossCompiler::TransformAST (TIntermNode *root)
PropagateMutableUniforms (root, infoSink);
}
-void HlslCrossCompiler::ProduceGLSL (TIntermNode *root, bool usePrecision)
+void HlslCrossCompiler::ProduceGLSL (TIntermNode *root, TTranslateOptions options)
{
m_GlslProduced = true;
- TGlslOutputTraverser glslTraverse (infoSink, functionList, structList, usePrecision);
+ TGlslOutputTraverser glslTraverse (infoSink, functionList, structList, options);
root->traverse(&glslTraverse);
}
View
2  hlslang/GLSLCodeGen/hlslCrossCompiler.h
@@ -24,7 +24,7 @@ class HlslCrossCompiler
TInfoSink& getInfoSink() { return infoSink; }
void TransformAST (TIntermNode* root);
- void ProduceGLSL (TIntermNode* root, bool usePrecision);
+ void ProduceGLSL (TIntermNode* root, TTranslateOptions options);
bool IsASTTransformed() const { return m_ASTTransformed; }
bool IsGlslProduced() const { return m_GlslProduced; }
View
848 hlslang/GLSLCodeGen/hlslLinker.cpp
@@ -12,6 +12,7 @@
#include "osinclude.h"
#include <algorithm>
#include <string.h>
+#include <set>
// String table that maps attribute semantics to built-in GLSL attributes
static const char attribString[EAttrSemCount][32] = {
@@ -40,6 +41,9 @@ static const char attribString[EAttrSemCount][32] = {
"xlat_attrib_blendindices",
"",
"",
+ "gl_VertexID",
+ "gl_InstanceIDARB",
+ ""
};
// String table that maps attribute semantics to built-in GLSL output varyings
@@ -69,6 +73,9 @@ static const char varOutString[EAttrSemCount][32] = {
"",
"",
"",
+ "",
+ "",
+ ""
};
// String table that maps attribute semantics to built-in GLSL input varyings
@@ -98,6 +105,9 @@ static const char varInString[EAttrSemCount][32] = {
"",
"",
"",
+ "",
+ "",
+ "gl_PrimitiveID"
};
// String table that maps attribute semantics to built-in GLSL fragment shader outputs
@@ -241,7 +251,7 @@ bool HlslLinker::getArgumentData2( const std::string &name, const std::string &s
case EClassVarOut:
// If using user varyings, create a user varying name
- if ( (bUserVaryings && sem != EAttrSemPosition) || varOutString[sem][0] == 0 )
+ if ( (bUserVaryings && sem != EAttrSemPosition && sem != EAttrSemPrimitiveID) || varOutString[sem][0] == 0 )
{
outName = kUserVaryingPrefix;
outName += semantic;
@@ -265,7 +275,7 @@ bool HlslLinker::getArgumentData2( const std::string &name, const std::string &s
case EClassVarIn:
// If using user varyings, create a user varying name
- if ( (bUserVaryings && sem != EAttrSemVPos && sem != EAttrSemVFace) || varInString[sem][0] == 0 )
+ if ( (bUserVaryings && sem != EAttrSemVPos && sem != EAttrSemVFace && sem != EAttrSemPrimitiveID) || varInString[sem][0] == 0 )
{
outName = kUserVaryingPrefix;
outName += stripSemanticModifier ( semantic, false );
@@ -402,6 +412,9 @@ static AttrSemanticMapping kAttributeSemantic[] = {
{ "texcoord8", EAttrSemTex8 },
{ "texcoord9", EAttrSemTex9 },
{ "depth", EAttrSemDepth },
+ { "sv_vertexid", EAttrSemVertexID },
+ { "sv_primitiveid", EAttrSemPrimitiveID },
+ { "sv_instanceid", EAttrSemInstanceID }
};
// Determine the GLSL attribute semantic for a given HLSL semantic
@@ -474,7 +487,6 @@ static void EmitCalledFunctions (std::stringstream& shader, const FunctionSet& f
shader << "\n";
OutputLineDirective(shader, (*fit)->getLine());
shader << (*fit)->getPrototype() << " {\n";
- shader << (*fit)->getLocalDecls(1) << "\n";
shader << (*fit)->getCode() << "\n"; //has embedded }
shader << "\n";
}
@@ -497,7 +509,14 @@ static const char* GetEntryName (const char* entryFunc)
static const char* kShaderTypeNames[2] = { "Vertex", "Fragment" };
-
+void HlslLinker::addRequiredExtensions(EAttribSemantic sem, ExtensionSet &extensions)
+{
+ if (sem == EAttrSemPrimitiveID || sem == EAttrSemVertexID)
+ extensions.insert("GL_EXT_gpu_shader4");
+
+ if (sem == EAttrSemInstanceID)
+ extensions.insert("GL_ARB_draw_instanced");
+}
bool HlslLinker::link(HlslCrossCompiler* compiler, const char* entryFunc, bool usePrecision)
{
@@ -558,34 +577,29 @@ bool HlslLinker::link(HlslCrossCompiler* compiler, const char* entryFunc, bool u
//add all the called functions to the list
calledFunctions.push_back (funcMain);
if (!addCalledFunctions (funcMain, calledFunctions, functionList))
- {
infoSink.info << "Failed to resolve all called functions in the " << kShaderTypeNames[lang] << " shader\n";
- }
//iterate over the functions, building a global list of structure declaractions and symbols
// assume a single compilation unit for expediency (eliminates name clashes, as type checking
// withing a single compilation unit has been performed)
- for (FunctionSet::iterator it=calledFunctions.begin(); it != calledFunctions.end(); it++)
- {
- //get each symbol and each structure, and add them to the map
- // checking that any previous entries are equivalent
- const std::vector<GlslSymbol*> &symList = (*it)->getSymbols();
-
- for (std::vector<GlslSymbol*>::const_iterator cit = symList.begin(); cit < symList.end(); cit++)
- {
- if ( (*cit)->getIsGlobal())
- {
- //should check for already added ones here
- globalSymMap[(*cit)->getName()] = *cit;
- }
+ std::vector<GlslSymbol*> constants;
+ for (FunctionSet::iterator it = calledFunctions.begin(); it != calledFunctions.end(); ++it) {
+ const std::vector<GlslSymbol*> &symbols = (*it)->getSymbols();
+
+ unsigned n_symbols = symbols.size();
+ for (unsigned i = 0; i != n_symbols; ++i) {
+ GlslSymbol* s = symbols[i];
+ if (s->getQualifier() == EqtUniform || s->getQualifier() == EqtMutableUniform)
+ constants.push_back(s);
}
-
+
//take each referenced library function, and add it to the set
- const std::set<TOperator> &libSet = (*it)->getLibFunctions();
-
- libFunctions.insert( libSet.begin(), libSet.end());
+ const std::set<TOperator> &referencedFunctions = (*it)->getLibFunctions();
+ libFunctions.insert( referencedFunctions.begin(), referencedFunctions.end());
}
-
+
+ // Remove duplicates
+ constants.resize(std::unique(constants.begin(), constants.end()) - constants.begin());
// The following code is what is used to generate the actual shader and "main"
// function. The process is to take all the components collected above, and
@@ -633,22 +647,37 @@ bool HlslLinker::link(HlslCrossCompiler* compiler, const char* entryFunc, bool u
}
//
- // Write global variables
+ // Write global scope
//
-
- if (!globalSymMap.empty())
- {
- for (std::map<std::string,GlslSymbol*>::iterator sit = globalSymMap.begin(); sit != globalSymMap.end(); sit++)
- {
- sit->second->writeDecl(shader,false,false);
- shader << ";\n";
-
- if ( sit->second->getIsMutable() )
- {
- sit->second->writeDecl(shader, true, false);
- shader << ";\n";
- }
+ unsigned n_func = globalList.size();
+ for (unsigned i = 0; i != n_func; ++i)
+ shader << globalList[i]->getCode();
+
+ // Write mutable uniform declarations and populate unfiform reflection.
+ unsigned n_constants = constants.size();
+ for (unsigned i = 0; i != n_constants; ++i) {
+ GlslSymbol* s = constants[i];
+ if (s->getIsMutable()) {
+ s->writeDecl(shader, true, false);
+ shader << ";\n";
}
+
+ ShUniformInfo info;
+ const std::string& name = s->getName(false);
+ info.name = new char[name.size()+1];
+ strcpy(info.name, name.c_str());
+
+ if (s->getSemantic() != "") {
+ info.semantic = new char[s->getSemantic().size()+1];
+ strcpy(info.semantic, s->getSemantic().c_str());
+ }
+ else
+ info.semantic = 0;
+
+ info.type = (EShType)s->getType();
+ info.arraySize = s->getArraySize();
+ info.init = 0;
+ uniforms.push_back(info);
}
//
@@ -656,512 +685,471 @@ bool HlslLinker::link(HlslCrossCompiler* compiler, const char* entryFunc, bool u
//
EmitCalledFunctions (shader, calledFunctions);
- //
- // Gather the uniforms into the uniform list
- //
- for (std::map<std::string, GlslSymbol*>::iterator it = globalSymMap.begin(); it != globalSymMap.end(); it++)
- {
- if (it->second->getQualifier() != EqtUniform)
- continue;
-
- ShUniformInfo infoStruct;
- infoStruct.name = new char[it->first.size()+1];
- strcpy( infoStruct.name, it->first.c_str());
- if (it->second->getSemantic() != "")
- {
- infoStruct.semantic = new char[it->second->getSemantic().size()+1];
- strcpy( infoStruct.semantic, it->second->getSemantic().c_str());
- }
- else
- infoStruct.semantic = 0;
-
- //gigantic hack, the enumerations are kept in alignment
- infoStruct.type = (EShType)it->second->getType();
- infoStruct.arraySize = it->second->getArraySize();
-
- if ( it->second->hasInitializer() )
- {
- int initSize = it->second->initializerSize();
- infoStruct.init = new float[initSize];
- memcpy( infoStruct.init, it->second->getInitializer(), sizeof(float) * initSize);
- }
- else
- infoStruct.init = 0;
-
- //TODO: need to add annotation
-
- uniforms.push_back( infoStruct);
- }
-
//
// Generate the main function
//
-
- std::stringstream attrib;
- std::stringstream uniform;
- std::stringstream preamble;
- std::stringstream postamble;
- std::stringstream varying;
- std::stringstream call;
- const int pCount = funcMain->getParameterCount();
-
- preamble << "void main() {\n";
- const EGlslSymbolType retType = funcMain->getReturnType();
- GlslStruct *retStruct = funcMain->getStruct();
- if ( retType == EgstStruct)
+ ExtensionSet extensions;
+ std::stringstream attrib;
+ std::stringstream uniform;
+ std::stringstream preamble;
+ std::stringstream postamble;
+ std::stringstream varying;
+ std::stringstream call;
+ const int pCount = funcMain->getParameterCount();
+
+ preamble << "void main() {\n";
+ const EGlslSymbolType retType = funcMain->getReturnType();
+ GlslStruct *retStruct = funcMain->getStruct();
+ if ( retType == EgstStruct)
+ {
+ assert(retStruct);
+ preamble << " " << retStruct->getName() << " xl_retval;\n";
+ }
+ else
+ {
+ if ( retType != EgstVoid)
{
- assert(retStruct);
- preamble << " " << retStruct->getName() << " xl_retval;\n";
- }
- else
- {
- if ( retType != EgstVoid)
- {
- preamble << " ";
- writeType (preamble, retType, NULL, usePrecision?funcMain->getPrecision():EbpUndefined);
- preamble << " xl_retval;\n";
- }
- }
-
- // Write all mutable initializations
- if ( calledFunctions.size() > 0 )
- {
- for (FunctionSet::iterator fit = calledFunctions.begin(); fit != calledFunctions.end(); fit++)
- {
- std::string mutableDecls = (*fit)->getMutableDecls(1, calledFunctions.begin(), fit);
-
- if ( mutableDecls.size() > 0 )
- {
- preamble << mutableDecls;
- }
- }
+ preamble << " ";
+ writeType (preamble, retType, NULL, usePrecision?funcMain->getPrecision():EbpUndefined);
+ preamble << " xl_retval;\n";
}
+ }
+
+ call << " ";
+ if (retType != EgstVoid)
+ call << "xl_retval = " << funcMain->getName() << "( ";
+ else
+ call << funcMain->getName() << "( ";
- call << " ";
- if (retType != EgstVoid)
- call << "xl_retval = " << funcMain->getName() << "( ";
- else
- call << funcMain->getName() << "( ";
+ // pass main function parameters
+ for (int ii=0; ii<pCount; ii++)
+ {
+ GlslSymbol *sym = funcMain->getParameter(ii);
+ EAttribSemantic attrSem = parseAttributeSemantic( sym->getSemantic());
+
+ addRequiredExtensions(attrSem, extensions);
- // pass main function parameters
- for (int ii=0; ii<pCount; ii++)
+ switch (sym->getQualifier())
{
- GlslSymbol *sym = funcMain->getParameter(ii);
- EAttribSemantic attrSem = parseAttributeSemantic( sym->getSemantic());
- switch (sym->getQualifier())
+ // -------- IN & OUT parameters
+ case EqtIn:
+ case EqtInOut:
+ case EqtConst:
+ if ( sym->getType() != EgstStruct)
{
+ std::string name, ctor;
+ int pad;
- // -------- IN & OUT parameters
- case EqtIn:
- case EqtInOut:
- case EqtConst:
- if ( sym->getType() != EgstStruct)
+ if ( getArgumentData( sym, lang==EShLangVertex ? EClassAttrib : EClassVarIn, name, ctor, pad) )
{
- std::string name, ctor;
- int pad;
+ // In fragment shader, pass zero for POSITION inputs
+ bool ignoredPositionInFragment = false;
+ if (lang == EShLangFragment && attrSem == EAttrSemPosition)
+ {
+ call << ctor << "(0.0)";
+ ignoredPositionInFragment = true;
+ }
+ // For "in" parameters, just call directly to the main
+ else if ( sym->getQualifier() != EqtInOut )
+ {
+ call << ctor << "(" << name;
+ for (int ii = 0; ii<pad; ii++)
+ call << ", 0.0";
+ call << ")";
+ }
+ // For "inout" parameters, declare a temp and initialize the temp
+ else
+ {
+ preamble << " ";
+ writeType (preamble, sym->getType(), NULL, usePrecision?sym->getPrecision():EbpUndefined);
+ preamble << " xlt_" << sym->getName() << " = ";
+ preamble << ctor << "(" << name;
+ for (int ii = 0; ii<pad; ii++)
+ preamble << ", 0.0";
+ preamble << ");\n";
+ }
- if ( getArgumentData( sym, lang==EShLangVertex ? EClassAttrib : EClassVarIn, name, ctor, pad) )
+ if (lang == EShLangVertex) // vertex shader: deal with gl_ attributes
{
- // In fragment shader, pass zero for POSITION inputs
- bool ignoredPositionInFragment = false;
- if (lang == EShLangFragment && attrSem == EAttrSemPosition)
+ if ( strncmp( name.c_str(), "gl_", 3))
{
- call << ctor << "(0.0)";
- ignoredPositionInFragment = true;
- }
- // For "in" parameters, just call directly to the main
- else if ( sym->getQualifier() != EqtInOut )
- {
- call << ctor << "(" << name;
- for (int ii = 0; ii<pad; ii++)
- call << ", 0.0";
- call << ")";
- }
- // For "inout" parameters, declare a temp and initialize the temp
- else
- {
- preamble << " ";
- writeType (preamble, sym->getType(), NULL, usePrecision?sym->getPrecision():EbpUndefined);
- preamble << " xlt_" << sym->getName() << " = ";
- preamble << ctor << "(" << name;
- for (int ii = 0; ii<pad; ii++)
- preamble << ", 0.0";
- preamble << ");\n";
- }
+ int typeOffset = 0;
- if (lang == EShLangVertex) // vertex shader: deal with gl_ attributes
- {
- if ( strncmp( name.c_str(), "gl_", 3))
+ // If the type is integer or bool based, we must convert to a float based
+ // type. This is because GLSL does not allow int or bool based vertex attributes.
+ if ( sym->getType() >= EgstInt && sym->getType() <= EgstInt4)
{
- int typeOffset = 0;
-
- // If the type is integer or bool based, we must convert to a float based
- // type. This is because GLSL does not allow int or bool based vertex attributes.
- if ( sym->getType() >= EgstInt && sym->getType() <= EgstInt4)
- {
- typeOffset += 4;
- }
-
- if ( sym->getType() >= EgstBool && sym->getType() <= EgstBool4)
- {
- typeOffset += 8;
- }
+ typeOffset += 4;
+ }
- // This is an undefined attribute
- attrib << "attribute " << getTypeString((EGlslSymbolType)(sym->getType() + typeOffset)) << " " << name << ";\n";
+ if ( sym->getType() >= EgstBool && sym->getType() <= EgstBool4)
+ {
+ typeOffset += 8;
}
- }
- if (lang == EShLangFragment) // deal with varyings
- {
- if (!ignoredPositionInFragment)
- AddToVaryings (varying, sym->getPrecision(), ctor, name);
+ // This is an undefined attribute
+ attrib << "attribute " << getTypeString((EGlslSymbolType)(sym->getType() + typeOffset)) << " " << name << ";\n";
}
}
- else
+
+ if (lang == EShLangFragment) // deal with varyings
{
- //should deal with fall through cases here
- assert(0);
- infoSink.info << "Unsupported type for shader entry parameter (";
- infoSink.info << getTypeString(sym->getType()) << ")\n";
+ if (!ignoredPositionInFragment)
+ AddToVaryings (varying, sym->getPrecision(), ctor, name);
}
}
else
{
- //structs must pass the struct, then process per element
- GlslStruct *Struct = sym->getStruct();
- assert(Struct);
-
- //first create the temp
- std::string tempVar = "xlt_" + sym->getName();
- preamble << " " << Struct->getName() << " ";
- preamble << tempVar <<";\n";
- call << tempVar;
+ //should deal with fall through cases here
+ assert(0);
+ infoSink.info << "Unsupported type for shader entry parameter (";
+ infoSink.info << getTypeString(sym->getType()) << ")\n";
+ }
+ }
+ else
+ {
+ //structs must pass the struct, then process per element
+ GlslStruct *Struct = sym->getStruct();
+ assert(Struct);
+
+ //first create the temp
+ std::string tempVar = "xlt_" + sym->getName();
+ preamble << " " << Struct->getName() << " ";
+ preamble << tempVar <<";\n";
+ call << tempVar;
+
+ const int elem = Struct->memberCount();
+ for (int jj=0; jj<elem; jj++)
+ {
+ const GlslStruct::member &current = Struct->getMember(jj);
+ EAttribSemantic memberSem = parseAttributeSemantic (current.semantic);
+ std::string name, ctor;
+ int pad;
+ int numArrayElements = 1;
+ bool bIsArray = false;
+
+ addRequiredExtensions(memberSem, extensions);
- const int elem = Struct->memberCount();
- for (int jj=0; jj<elem; jj++)
+ // If it is an array, loop over each member
+ if ( current.arraySize > 0 )