\r
layout(location = 50, component = 3) out int be;\r
layout(location = 50, component = 0) out vec3 bf;\r
+\r
+out bblck1 {\r
+ vec4 bbv;\r
+} bbinst1;\r
+\r
+out bblck2 {\r
+ layout(xfb_offset=16) vec4 bbv;\r
+} bbinst2;\r
+\r
+layout(xfb_buffer = 3, xfb_stride = 16) out;\r
+\r
+out bblck3 {\r
+ layout(xfb_offset=16) vec4 bbv;\r
+} bbinst3;\r
+\r
+uniform ubblck3 {\r
+ layout(xfb_offset=16) vec4 bbv; // ERROR\r
+} ubbinst3;\r
+\r
+layout(xfb_buffer=2, xfb_offset=32, xfb_stride=64) out vec4 bg;\r
+layout( xfb_offset=32, xfb_stride=64) out vec4 bh;\r
+\r
+layout(xfb_offset=48) out; // ERROR\r
+\r
+layout(xfb_stride=32, xfb_buffer=2, xfb_offset=16) out bblck4 {\r
+ vec4 bbv1;\r
+ vec4 bbv2;\r
+} bbinst4;\r
+\r
+out bblck5 {\r
+ layout(xfb_offset=0) vec4 bbv1;\r
+ layout(xfb_stride=32, xfb_buffer=3, xfb_offset=16) vec4 bbv2;\r
+ layout(xfb_buffer=2) vec4 bbv3; // ERROR, wrong buffer\r
+} bbinst5;\r
ERROR: 0:57: 'component' : cannot apply to a matrix, structure, or block \r
ERROR: 0:58: 'component' : cannot apply to a matrix, structure, or block \r
ERROR: 0:61: 'location' : cannot declare a default, use a full declaration \r
-ERROR: 19 compilation errors. No code generated.\r
+ERROR: 0:81: 'xfb layout qualifier' : can only be used on an output \r
+ERROR: 0:87: 'xfb_offset' : cannot declare a default, use a full declaration \r
+ERROR: 0:97: 'xfb_buffer' : member cannot contradict block (or what block inherited from global) \r
+ERROR: 22 compilation errors. No code generated.\r
\r
\r
+in xfb mode\r
ERROR: node is still EOpNull!\r
0:? Linker Objects\r
0:? 'a' (layout(location=2 component=2 ) in 2-component vector of float)\r
0:? 'bd' (out block{layout(location=40 component=2 ) out float u, layout(location=40 component=0 ) out float v, layout(location=40 component=3 ) out float w, layout(location=40 component=1 ) out 2-component vector of float x, layout(location=41 component=3 ) out 2-component vector of float y, layout(location=42 component=1 ) out 4-component vector of float z, layout(location=42 component=1 ) out 4X4 matrix of float ba, layout(location=43 component=1 ) out structure{int a} Ss})\r
0:? 'be' (layout(location=50 component=3 ) smooth out int)\r
0:? 'bf' (layout(location=50 component=0 ) smooth out 3-component vector of float)\r
+0:? 'bbinst1' (out block{out 4-component vector of float bbv})\r
+0:? 'bbinst2' (out block{layout(xfb_buffer=0 xfb_offset=16 ) out 4-component vector of float bbv})\r
+0:? 'bbinst3' (out block{layout(xfb_buffer=3 xfb_offset=16 ) out 4-component vector of float bbv})\r
+0:? 'ubbinst3' (layout(column_major shared ) uniform block{layout(column_major shared xfb_offset=16 ) uniform 4-component vector of float bbv})\r
+0:? 'bg' (layout(xfb_buffer=2 xfb_offset=32 xfb_stride=64 ) smooth out 4-component vector of float)\r
+0:? 'bh' (layout(xfb_buffer=3 xfb_offset=32 xfb_stride=64 ) smooth out 4-component vector of float)\r
+0:? 'bbinst4' (layout(xfb_buffer=2 xfb_offset=16 xfb_stride=32 ) out block{layout(xfb_buffer=2 xfb_offset=16 ) out 4-component vector of float bbv1, layout(xfb_buffer=2 xfb_offset=16 ) out 4-component vector of float bbv2})\r
+0:? 'bbinst5' (out block{layout(xfb_buffer=3 xfb_offset=0 ) out 4-component vector of float bbv1, layout(xfb_buffer=3 xfb_offset=16 xfb_stride=32 ) out 4-component vector of float bbv2, out 4-component vector of float bbv3})\r
0:? 'gl_VertexID' (gl_VertexId int)\r
0:? 'gl_InstanceID' (gl_InstanceId int)\r
\r
\r
ERROR: Linking vertex stage: Missing entry point: Each stage requires one "void main()" entry point\r
\r
+in xfb mode\r
\r
writeonly = false;
clearLayout();
}
- TStorageQualifier storage : 6;
+ TStorageQualifier storage : 6;
TPrecisionQualifier precision : 3;
bool invariant : 1;
bool centroid : 1;
}
bool hasXfb() const
{
- return layoutXfbBuffer != layoutXfbBufferEnd ||
- layoutXfbStride != layoutXfbStrideEnd ||
- layoutXfbOffset != layoutXfbOffsetEnd;
+ return hasXfbBuffer() ||
+ hasXfbStride() ||
+ hasXfbOffset();
+ }
+ bool hasXfbBuffer() const
+ {
+ return layoutXfbBuffer != layoutXfbBufferEnd;
+ }
+ bool hasXfbStride() const
+ {
+ return layoutXfbStride != layoutXfbStrideEnd;
+ }
+ bool hasXfbOffset() const
+ {
+ return layoutXfbOffset != layoutXfbOffsetEnd;
}
static const char* getLayoutPackingString(TLayoutPacking packing)
{
{
sampler.clear();
qualifier.clear();
- typeName = NewPoolTString(n.c_str());
+ typeName = NewPoolTString(n.c_str());
}
// For interface blocks
TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
qualifier(q), arraySizes(0), structure(userDef), fieldName(0)
{
sampler.clear();
- typeName = NewPoolTString(n.c_str());
+ typeName = NewPoolTString(n.c_str());
}
virtual ~TType() {}
// the instances are sharing the same pool.
void shallowCopy(const TType& copyOf)
{
- basicType = copyOf.basicType;
+ basicType = copyOf.basicType;
sampler = copyOf.sampler;
- qualifier = copyOf.qualifier;
- vectorSize = copyOf.vectorSize;
- matrixCols = copyOf.matrixCols;
- matrixRows = copyOf.matrixRows;
+ qualifier = copyOf.qualifier;
+ vectorSize = copyOf.vectorSize;
+ matrixCols = copyOf.matrixCols;
+ matrixRows = copyOf.matrixRows;
arraySizes = copyOf.arraySizes;
structure = copyOf.structure;
structureSize = copyOf.structureSize;
- fieldName = copyOf.fieldName;
- typeName = copyOf.typeName;
+ fieldName = copyOf.fieldName;
+ typeName = copyOf.typeName;
}
- void deepCopy(const TType& copyOf)
- {
+ void deepCopy(const TType& copyOf)
+ {
shallowCopy(copyOf);
if (arraySizes) {
*arraySizes = *copyOf.arraySizes;
}
- if (structure) {
- structure = new TTypeList;
- TStructureMapIterator iter;
- for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
- TTypeLoc typeLoc;
- typeLoc.loc = (*copyOf.structure)[i].loc;
- typeLoc.type = new TType();
- typeLoc.type->deepCopy(*(*copyOf.structure)[i].type);
- structure->push_back(typeLoc);
- }
- }
-
- if (fieldName)
- fieldName = NewPoolTString(copyOf.fieldName->c_str());
- if (typeName)
- typeName = NewPoolTString(copyOf.typeName->c_str());
- }
+ if (structure) {
+ structure = new TTypeList;
+ TStructureMapIterator iter;
+ for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
+ TTypeLoc typeLoc;
+ typeLoc.loc = (*copyOf.structure)[i].loc;
+ typeLoc.type = new TType();
+ typeLoc.type->deepCopy(*(*copyOf.structure)[i].type);
+ structure->push_back(typeLoc);
+ }
+ }
+
+ if (fieldName)
+ fieldName = NewPoolTString(copyOf.fieldName->c_str());
+ if (typeName)
+ typeName = NewPoolTString(copyOf.typeName->c_str());
+ }
TType* clone()
- {
- TType *newType = new TType();
- newType->deepCopy(*this);
+ {
+ TType *newType = new TType();
+ newType->deepCopy(*this);
- return newType;
- }
+ return newType;
+ }
// Merge type from parent, where a parentType is at the beginning of a declaration,
// establishing some charastics for all subsequent names, while this type
virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
virtual const TString& getTypeName() const
{
- assert(typeName);
- return *typeName;
+ assert(typeName);
+ return *typeName;
}
virtual const TString& getFieldName() const
{
- assert(fieldName);
- return *fieldName;
+ assert(fieldName);
+ return *fieldName;
}
virtual TBasicType getBasicType() const { return basicType; }
virtual bool isScalar() const { return vectorSize == 1 && ! isStruct() && ! isArray(); }
virtual bool isVector() const { return vectorSize > 1; }
- virtual bool isMatrix() const { return matrixCols ? true : false; }
+ virtual bool isMatrix() const { return matrixCols ? true : false; }
virtual bool isArray() const { return arraySizes != 0; }
virtual bool isStruct() const { return structure != 0; }
{
if (isArray())
return true;
- if (! structure)
+ if (! structure)
return false;
- for (unsigned int i = 0; i < structure->size(); ++i) {
+ for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsArray())
return true;
}
const int maxSize = GlslangMaxTypeLength;
char buf[maxSize];
char *p = &buf[0];
- char *end = &buf[maxSize];
+ char *end = &buf[maxSize];
if (qualifier.hasLayout()) {
- p += snprintf(p, end - p, "layout(");
- if (qualifier.hasLocation()) {
- p += snprintf(p, end - p, "location=%d ", qualifier.layoutLocation);
- if (qualifier.layoutComponent != qualifier.layoutComponentEnd)
- p += snprintf(p, end - p, "component=%d ", qualifier.layoutComponent);
+ // To reduce noise, skip this if the only layout is an xfb_buffer
+ // with no triggering xfb_offset.
+ TQualifier noXfbBuffer = qualifier;
+ noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
+ if (noXfbBuffer.hasLayout()) {
+ p += snprintf(p, end - p, "layout(");
+ if (qualifier.hasLocation()) {
+ p += snprintf(p, end - p, "location=%d ", qualifier.layoutLocation);
+ if (qualifier.layoutComponent != qualifier.layoutComponentEnd)
+ p += snprintf(p, end - p, "component=%d ", qualifier.layoutComponent);
+ }
+ if (qualifier.hasBinding())
+ p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding);
+ if (qualifier.hasStream())
+ p += snprintf(p, end - p, "stream=%d ", qualifier.layoutStream);
+ if (qualifier.layoutMatrix != ElmNone)
+ p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
+ if (qualifier.layoutPacking != ElpNone)
+ p += snprintf(p, end - p, "%s ", TQualifier::getLayoutPackingString(qualifier.layoutPacking));
+ if (qualifier.layoutOffset != -1)
+ p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset);
+ if (qualifier.layoutAlign != -1)
+ p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign);
+
+ if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset())
+ p += snprintf(p, end - p, "xfb_buffer=%d ", qualifier.layoutXfbBuffer);
+ if (qualifier.hasXfbOffset())
+ p += snprintf(p, end - p, "xfb_offset=%d ", qualifier.layoutXfbOffset);
+ if (qualifier.hasXfbStride())
+ p += snprintf(p, end - p, "xfb_stride=%d ", qualifier.layoutXfbStride);
+ p += snprintf(p, end - p, ") ");
}
- if (qualifier.hasBinding())
- p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding);
- if (qualifier.hasStream())
- p += snprintf(p, end - p, "stream=%d ", qualifier.layoutStream);
- if (qualifier.layoutMatrix != ElmNone)
- p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
- if (qualifier.layoutPacking != ElpNone)
- p += snprintf(p, end - p, "%s ", TQualifier::getLayoutPackingString(qualifier.layoutPacking));
- if (qualifier.layoutOffset != -1)
- p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset);
- if (qualifier.layoutAlign != -1)
- p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign);
-
- if (qualifier.layoutXfbBuffer != qualifier.layoutXfbBufferEnd)
- p += snprintf(p, end - p, "xfb_buffer=%d ", qualifier.layoutXfbBuffer);
- if (qualifier.layoutXfbOffset != qualifier.layoutXfbOffsetEnd)
- p += snprintf(p, end - p, "xfb_offset=%d ", qualifier.layoutXfbOffset);
- if (qualifier.layoutXfbStride != qualifier.layoutXfbStrideEnd)
- p += snprintf(p, end - p, "xfb_stride=%d ", qualifier.layoutXfbStride);
- p += snprintf(p, end - p, ") ");
}
if (qualifier.invariant)
void buildMangledName(TString&);
int getStructSize() const;
- TBasicType basicType : 8;
+ TBasicType basicType : 8;
int vectorSize : 4;
int matrixCols : 4;
int matrixRows : 4;
TTypeList* structure; // 0 unless this is a struct
mutable int structureSize; // a cache, updated on first access
- TString *fieldName; // for structure field names
- TString *typeName; // for structure type name
+ TString *fieldName; // for structure field names
+ TString *typeName; // for structure type name
};
} // end namespace glslang
// source have to figure out how to create revision.h just to get a build\r
// going. However, if it is not updated, it can be a version behind.\r
\r
-#define GLSLANG_REVISION "24740"\r
-#define GLSLANG_DATE "2014/01/11 12:29:55"\r
+#define GLSLANG_REVISION "24741"\r
+#define GLSLANG_DATE "2014/01/11 13:35:26"\r
globalBufferDefaults.layoutMatrix = ElmColumnMajor;
globalBufferDefaults.layoutPacking = ElpShared;
- // TODO: 4.4 enhanced layouts: defaults for xfb?
-
globalInputDefaults.clear();
globalOutputDefaults.clear();
+ if (language == EShLangVertex ||
+ language == EShLangTessControl ||
+ language == EShLangTessEvaluation ||
+ language == EShLangGeometry)
+ globalOutputDefaults.layoutXfbBuffer = 0;
if (language == EShLangGeometry)
globalOutputDefaults.layoutStream = 0;
}
case EShLangCompute:
break;
- default:
+ default:
break;
}
} else {
case EShLangCompute:
break;
- default:
+ default:
break;
}
}
publicType.qualifier.layoutComponent = value;
return;
} else if (id.compare(0, 4, "xfb_") == 0) {
+ intermediate.setXfbMode();
const char* feature = "transform feedback qualifier";
requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature);
requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
error(loc, "buffer is too large", id.c_str(), "");
else
publicType.qualifier.layoutXfbBuffer = value;
+ return;
} else if (id == "xfb_offset") {
if (value >= TQualifier::layoutXfbOffsetEnd) // TODO: 4.4 enhanced layouts: also check against gl_MaxTransformFeedbackInterleavedComponents
error(loc, "offset is too large", id.c_str(), "");
else
publicType.qualifier.layoutXfbOffset = value;
+ return;
} else if (id == "xfb_stride") {
- if (value >= TQualifier::layoutXfbStrideEnd) // TODO: 4.4 enhanced layouts: also check against gl_MaxTransformFeedbackInterleavedComponents
+ if (value >= TQualifier::layoutXfbStrideEnd) // TODO: 4.4 enhanced layouts: also check against 4*gl_MaxTransformFeedbackInterleavedComponents
error(loc, "stride is too large", id.c_str(), "");
else
publicType.qualifier.layoutXfbStride = value;
+ return;
}
}
case EShLangCompute:
break;
- default:
+ default:
break;
}
if (src.hasStream())
dst.layoutStream = src.layoutStream;
- if (src.layoutXfbBuffer != TQualifier::layoutXfbBufferEnd)
+ if (src.hasXfbBuffer())
dst.layoutXfbBuffer = src.layoutXfbBuffer;
+ if (src.hasXfbOffset())
+ dst.layoutXfbOffset = src.layoutXfbOffset;
if (! inheritOnly) {
if (src.layoutLocation != TQualifier::layoutLocationEnd)
if (src.layoutBinding != TQualifier::layoutBindingEnd)
dst.layoutBinding = src.layoutBinding;
- if (src.layoutXfbStride != TQualifier::layoutXfbStrideEnd)
+ if (src.hasXfbStride())
dst.layoutXfbStride = src.layoutXfbStride;
- if (src.layoutXfbOffset != TQualifier::layoutXfbOffsetEnd)
- dst.layoutXfbOffset = src.layoutXfbOffset;
}
}
if (qualifier.storage != EvqVaryingOut)
error(loc, "can only be used on an output", "stream", "");
}
+ if (qualifier.hasXfb()) {
+ if (qualifier.storage != EvqVaryingOut)
+ error(loc, "can only be used on an output", "xfb layout qualifier", "");
+ }
}
// For places that can't have shader-level layout qualifiers
invariantCheck(loc, type, identifier);
samplerCheck(loc, type, identifier);
- // Pick up defaults
- if (! type.getQualifier().hasStream() && language == EShLangGeometry && type.getQualifier().storage == EvqVaryingOut)
- type.getQualifier().layoutStream = globalOutputDefaults.layoutStream;
-
if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
if (! symbol)
reservedErrorCheck(loc, identifier);
+ inheritGlobalDefaults(type.getQualifier());
+
// Declare the variable
if (arraySizes || type.isArray()) {
// Arrayness is potentially coming both from the type and from the
return initNode;
}
+// Pick up global defaults from the provide global defaults into dst.
+void TParseContext::inheritGlobalDefaults(TQualifier& dst) const
+{
+ if (dst.storage == EvqVaryingOut) {
+ if (! dst.hasStream() && language == EShLangGeometry)
+ dst.layoutStream = globalOutputDefaults.layoutStream;
+ if (! dst.hasXfbBuffer())
+ dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
+ }
+}
+
//
// Declare a non-array variable, the main point being there is no redeclaration
// for resizing allowed.
if (defaultQualification.layoutStream != memberQualifier.layoutStream)
error(memberLoc, "member cannot contradict block", "stream", "");
}
+ if (memberQualifier.hasXfbBuffer()) {
+ if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer)
+ error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", "");
+ }
if (memberQualifier.layoutPacking != ElpNone)
error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), "");
if (memberQualifier.hasLocation()) {
case EvqVaryingOut:
if (qualifier.hasStream())
globalOutputDefaults.layoutStream = qualifier.layoutStream;
+ if (qualifier.hasXfbBuffer())
+ globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer;
break;
default:
error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", "");
error(loc, "cannot declare a default, include a type or full declaration", "binding", "");
if (qualifier.hasLocation())
error(loc, "cannot declare a default, use a full declaration", "location", "");
+ if (qualifier.hasXfbOffset())
+ error(loc, "cannot declare a default, use a full declaration", "xfb_offset", "");
}
//
protected:
void nonInitConstCheck(TSourceLoc, TString& identifier, TType& type);
+ void inheritGlobalDefaults(TQualifier& dst) const;
TVariable* declareNonArray(TSourceLoc, TString& identifier, TType&, bool& newDeclaration);
void declareArray(TSourceLoc, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
TIntermNode* executeInitializer(TSourceLoc, TString& identifier, TIntermTyped* initializer, TVariable* variable);
//
void TIntermediate::output(TInfoSink& infoSink, bool tree)
{
+ if (xfbMode)
+ infoSink.debug << "in xfb mode\n";
+
switch (language) {
case EShLangVertex:
break;
if (unit.pointMode)\r
pointMode = true;\r
\r
+ if (unit.xfbMode)\r
+ xfbMode = true;\r
+\r
if (unit.treeRoot == 0)\r
return;\r
\r
explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v),
numMains(0), numErrors(0), recursive(false),
invocations(0), vertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false),
- vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false) { }
+ vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), xfbMode(false) { }
bool postProcess(TIntermNode*, EShLanguage);
void output(TInfoSink&, bool tree);
void removeTree();
return true;
}
void setPointMode() { pointMode = true; }
+ void setXfbMode() { xfbMode = true; }
bool setOutputPrimitive(TLayoutGeometry p)
{
if (outputPrimitive != ElgNone)
TVertexSpacing vertexSpacing;
TVertexOrder vertexOrder;
bool pointMode;
+ bool xfbMode;
// for detecting recursion: pair is <caller, callee>
struct TCall {