--- /dev/null
+#version 420 core
+
+layout(depth_any) out float gl_FragDepth;
+layout(depth_greater) out float gl_FragDepth; // ERROR: redeclaration with different qualifier
+
+void main()
+{
+ gl_FragDepth = 0.3;
+}
+
+layout(depth_less) in float depth; // ERROR: depth_less only applies to gl_FragDepth
+layout(depth_any) out float gl_FragDepth; // ERROR, done after use
--- /dev/null
+420.frag\r
+Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.\r
+ERROR: 0:4: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth\r
+ERROR: 0:11: 'layout qualifier' : can only apply depth layout to gl_FragDepth \r
+ERROR: 0:12: 'gl_FragDepth' : cannot redeclare after use \r
+ERROR: 3 compilation errors. No code generated.\r
+\r
+\r
+Shader version: 420\r
+using depth_any\r
+ERROR: node is still EOpNull!\r
+0:6 Function Definition: main( (void)\r
+0:6 Function Parameters: \r
+0:8 Sequence\r
+0:8 move second child to first child (float)\r
+0:8 'gl_FragDepth' (gl_FragDepth float)\r
+0:8 Constant:\r
+0:8 0.300000\r
+0:? Linker Objects\r
+0:? 'gl_FragDepth' (gl_FragDepth float)\r
+0:? 'gl_FragDepth' (gl_FragDepth float)\r
+0:? 'depth' (smooth in float)\r
+\r
+\r
+Linked fragment stage:\r
+\r
+\r
+Shader version: 420\r
+using depth_any\r
+ERROR: node is still EOpNull!\r
+0:6 Function Definition: main( (void)\r
+0:6 Function Parameters: \r
+0:8 Sequence\r
+0:8 move second child to first child (float)\r
+0:8 'gl_FragDepth' (gl_FragDepth float)\r
+0:8 Constant:\r
+0:8 0.300000\r
+0:? Linker Objects\r
+0:? 'gl_FragDepth' (gl_FragDepth float)\r
+0:? 'gl_FragDepth' (gl_FragDepth float)\r
+0:? 'depth' (smooth in float)\r
+\r
ERROR: 0:102: 'color' : redefinition \r
ERROR: 0:103: 'index' : there is no such layout identifier for this stage taking an assigned value \r
ERROR: 0:104: 'location' : overlapping use of location 3\r
-ERROR: 0:106: 'depth_greater' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) \r
-ERROR: 0:112: 'depth_any' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) \r
-ERROR: 0:115: 'depth_greater' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) \r
-ERROR: 0:118: 'depth_less' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) \r
-ERROR: 0:121: 'depth_unchanged' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) \r
+ERROR: 0:112: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth\r
+ERROR: 0:118: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth\r
+ERROR: 0:121: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth\r
ERROR: 0:150: 'constructor' : constructing from a non-dereferenced array \r
ERROR: 0:150: '=' : cannot convert from 'const float' to '3-element array of 4-component vector of float'\r
ERROR: 0:152: 'constructor' : cannot convert parameter 1 from 'const 2-element array of 4-component vector of float' to '4-component vector of float'\r
ERROR: 0:227: 'in' : not allowed in nested scope \r
ERROR: 0:228: 'in' : not allowed in nested scope \r
ERROR: 0:232: 'out' : not allowed in nested scope \r
-ERROR: 45 compilation errors. No code generated.\r
+ERROR: 43 compilation errors. No code generated.\r
\r
\r
Shader version: 430\r
gl_FragCoord pixel center is integer\r
gl_FragCoord origin is upper left\r
using early_fragment_tests\r
+using depth_greater\r
ERROR: node is still EOpNull!\r
0:5 Sequence\r
0:5 move second child to first child (int)\r
gl_FragCoord pixel center is integer\r
gl_FragCoord origin is upper left\r
using early_fragment_tests\r
+using depth_greater\r
ERROR: node is still EOpNull!\r
0:5 Sequence\r
0:5 move second child to first child (int)\r
110scope.vert
300scope.vert
400.frag
+420.frag
420.vert
420.geom
420_size_gl_in.geom
ElfCount
};
+enum TLayoutDepth {
+ EldNone,
+ EldAny,
+ EldGreater,
+ EldLess,
+ EldUnchanged,
+
+ EldCount
+};
+
class TQualifier {
public:
void clear()
default: return "none";
}
}
+ static const char* getLayoutDepthString(TLayoutDepth d)
+ {
+ switch (d) {
+ case EldAny: return "depth_any";
+ case EldGreater: return "depth_greater";
+ case EldLess: return "depth_less";
+ case EldUnchanged: return "depth_unchanged";
+ default: return "none";
+ }
+ }
static const char* getGeometryString(TLayoutGeometry geometry)
{
switch (geometry) {
bool pointMode;
int localSize[3]; // compute shader
bool earlyFragmentTests; // fragment input
+ TLayoutDepth layoutDepth;
void init()
{
localSize[1] = 1;
localSize[2] = 1;
earlyFragmentTests = false;
+ layoutDepth = EldNone;
}
// Merge in characteristics from the 'src' qualifier. They can override when
}
if (src.earlyFragmentTests)
earlyFragmentTests = true;
+ if (src.layoutDepth)
+ layoutDepth = src.layoutDepth;
}
};
p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset);
if (qualifier.hasAlign())
p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign);
-
if (qualifier.hasFormat())
p += snprintf(p, end - p, "%s ", TQualifier::getLayoutFormatString(qualifier.layoutFormat));
-
if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset())
p += snprintf(p, end - p, "xfb_buffer=%d ", qualifier.layoutXfbBuffer);
if (qualifier.hasXfbOffset())
error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str());
if (qualifier.storage != EvqVaryingOut)
error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str());
- // TODO 4.2: gl_FragDepth redeclaration
- }
+ if (publicType.layoutDepth != EldNone) {
+ if (intermediate.inIoAccessed("gl_FragDepth"))
+ error(loc, "cannot redeclare after use", "gl_FragDepth", "");
+ if (! intermediate.setDepth(publicType.layoutDepth))
+ error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str());
+ }
+
+ }
// TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above
return symbol;
// Layout qualifier stuff.
//
-// Put the id's layout qualification into the public type. This is before we know any
-// type information for error checking.
+// Put the id's layout qualification into the public type, for qualifiers not having a number set.
+// This is before we know any type information for error checking.
void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, TString& id)
{
std::transform(id.begin(), id.end(), id.begin(), ::tolower);
publicType.shaderQualifiers.earlyFragmentTests = true;
return;
}
+ for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) {
+ if (id == TQualifier::getLayoutDepthString(depth)) {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 0, "depth layout qualifier");
+ publicType.shaderQualifiers.layoutDepth = depth;
+ return;
+ }
+ }
}
error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
}
-// Put the id's layout qualifier value into the public type. This is before we know any
-// type information for error checking.
+// Put the id's layout qualifier value into the public type, for qualifiers having a number set.
+// This is before we know any type information for error checking.
void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, TString& id, const TIntermTyped* node)
{
const char* feature = "layout-id value";
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 (identifier != "gl_FragDepth" && publicType.shaderQualifiers.layoutDepth != EldNone)
+ error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", "");
// Check for redeclaration of built-ins and/or attempting to declare a reserved name
bool newDeclaration = false; // true if a new entry gets added to the symbol table
infoSink.debug << "gl_FragCoord origin is upper left\n";
if (earlyFragmentTests)
infoSink.debug << "using early_fragment_tests\n";
+ if (depthLayout != EldNone)
+ infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n";
break;
case EShLangCompute:
if (! earlyFragmentTests)\r
earlyFragmentTests = unit.earlyFragmentTests;\r
\r
+ if (depthLayout == EldNone)\r
+ depthLayout = unit.depthLayout;\r
+ else if (depthLayout != unit.depthLayout)\r
+ error(infoSink, "Contradictory depth layouts");\r
+\r
if (inputPrimitive == ElgNone)\r
inputPrimitive = unit.inputPrimitive;\r
else if (inputPrimitive != unit.inputPrimitive)\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), earlyFragmentTests(false), xfbMode(false)
+ vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), xfbMode(false)
{
localSize[0] = 1;
localSize[1] = 1;
bool getPixelCenterInteger() const { return pixelCenterInteger; }
void setEarlyFragmentTests() { earlyFragmentTests = true; }
bool getEarlyFragmentTests() const { return earlyFragmentTests; }
+ bool setDepth(TLayoutDepth d)
+ {
+ if (depthLayout != EldNone)
+ return depthLayout == d;
+ depthLayout = d;
+ return true;
+ }
+ TLayoutDepth getDepth() const { return depthLayout; }
void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
void merge(TInfoSink&, TIntermediate&);
bool pointMode;
int localSize[3];
bool earlyFragmentTests;
+ TLayoutDepth depthLayout;
bool xfbMode;
typedef std::list<TCall> TGraph;