Add support for SPV_NV_geometry_shader_passthrough

This commit is contained in:
chaoc 2016-12-20 13:28:52 -08:00
parent 0ad6a4e60d
commit 6e5acae144
13 changed files with 153 additions and 8 deletions

View File

@ -32,11 +32,18 @@ enum Decoration;
enum Op; enum Op;
static const int GLSLextNVVersion = 100; static const int GLSLextNVVersion = 100;
static const int GLSLextNVRevision = 1; static const int GLSLextNVRevision = 2;
//SPV_NV_sample_mask_override_coverage //SPV_NV_sample_mask_override_coverage
const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage";
static const Decoration OverrideCoverageNV = static_cast<Decoration>(5248); static const Decoration OverrideCoverageNV = static_cast<Decoration>(5248);
//SPV_NV_geometry_shader_passthrough
const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough";
static const Decoration PassthroughNV = static_cast<Decoration>(5250);
static const Capability GeometryShaderPassthroughNV = static_cast<Capability>(5251);
#endif // #ifndef GLSLextNV_H #endif // #ifndef GLSLextNV_H

View File

@ -4738,6 +4738,11 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage); builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage);
} }
} }
if (symbol->getQualifier().layoutPassthrough) {
addDecoration(id, spv::PassthroughNV);
builder.addCapability(spv::GeometryShaderPassthroughNV);
builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
}
#endif #endif
return id; return id;

View File

@ -481,7 +481,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
extInstSet = GLSLextAMDInst; extInstSet = GLSLextAMDInst;
#endif #endif
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
} else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0) { }else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0) {
extInstSet = GLSLextNVInst; extInstSet = GLSLextNVInst;
#endif #endif
} }
@ -654,9 +655,12 @@ static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint) static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
{ {
if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0) { if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||
strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0) {
switch (entrypoint) { switch (entrypoint) {
case OverrideCoverageNV: return "OverrideCoverageNV"; case OverrideCoverageNV: return "OverrideCoverageNV";
case PassthroughNV: return "PassthroughNV";
case GeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
default: return "Bad"; default: return "Bad";
} }
} }

View File

@ -261,6 +261,7 @@ const char* DecorationString(int decoration)
#endif #endif
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
case 5248: return "OverrideCoverageNV"; case 5248: return "OverrideCoverageNV";
case 5250: return "PassthroughNV";
#endif #endif
} }
} }
@ -818,6 +819,11 @@ const char* CapabilityString(int info)
case 4423: return "SubgroupBallotKHR"; case 4423: return "SubgroupBallotKHR";
case 4427: return "DrawParameters"; case 4427: return "DrawParameters";
#ifdef NV_EXTENSIONS
case 5251: return "GeometryShaderPassthroughNV";
#endif
} }
} }

View File

@ -0,0 +1,46 @@
spv.GeometryShaderPassthrough.geom
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 15
Capability Geometry
Capability GeometryShaderPassthroughNV
Extension "SPV_NV_geometry_shader_passthrough"
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Geometry 4 "main" 10 14
ExecutionMode 4 Triangles
ExecutionMode 4 Invocations 1
ExecutionMode 4 OutputVertices
Source GLSL 450
SourceExtension "GL_NV_geometry_shader_passthrough"
Name 4 "main"
Name 8 "gl_PerVertex"
MemberName 8(gl_PerVertex) 0 "gl_Position"
Name 10 ""
Name 12 "Inputs"
MemberName 12(Inputs) 0 "texcoord"
MemberName 12(Inputs) 1 "baseColor"
Name 14 ""
MemberDecorate 8(gl_PerVertex) 0 BuiltIn Position
Decorate 8(gl_PerVertex) Block
Decorate 10 PassthroughNV
Decorate 12(Inputs) Block
Decorate 14 PassthroughNV
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8(gl_PerVertex): TypeStruct 7(fvec4)
9: TypePointer Input 8(gl_PerVertex)
10: 9(ptr) Variable Input
11: TypeVector 6(float) 2
12(Inputs): TypeStruct 11(fvec2) 7(fvec4)
13: TypePointer Input 12(Inputs)
14: 13(ptr) Variable Input
4(main): 2 Function None 3
5: Label
Return
FunctionEnd

View File

@ -0,0 +1,17 @@
#version 450
#extension GL_NV_geometry_shader_passthrough : require
layout(triangles) in;
layout(passthrough) in gl_PerVertex {
vec4 gl_Position;
};
layout(passthrough) in Inputs {
vec2 texcoord;
vec4 baseColor;
};
void main()
{
}

View File

@ -599,6 +599,9 @@ public:
layoutFormat = ElfNone; layoutFormat = ElfNone;
layoutPushConstant = false; layoutPushConstant = false;
#ifdef NV_EXTENSIONS
layoutPassthrough = false;
#endif
} }
bool hasLayout() const bool hasLayout() const
{ {
@ -652,6 +655,10 @@ public:
bool layoutPushConstant; bool layoutPushConstant;
#ifdef NV_EXTENSIONS
bool layoutPassthrough;
#endif
bool hasUniformLayout() const bool hasUniformLayout() const
{ {
return hasMatrix() || return hasMatrix() ||
@ -1537,6 +1544,12 @@ public:
if (qualifier.layoutPushConstant) if (qualifier.layoutPushConstant)
p += snprintf(p, end - p, "push_constant "); p += snprintf(p, end - p, "push_constant ");
#ifdef NV_EXTENSIONS
if (qualifier.layoutPassthrough)
p += snprintf(p, end - p, "passthrough ");
#endif
p += snprintf(p, end - p, ") "); p += snprintf(p, end - p, ") ");
} }
} }

View File

@ -604,7 +604,11 @@ void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type)
void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
{ {
if (! type.isArray() && ! symbolTable.atBuiltInLevel()) { if (! type.isArray() && ! symbolTable.atBuiltInLevel()) {
if (type.getQualifier().isArrayedIo(language)) if (type.getQualifier().isArrayedIo(language)
#ifdef NV_EXTENSIONS
&& !type.getQualifier().layoutPassthrough
#endif
)
error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str()); error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str());
} }
} }
@ -3459,6 +3463,20 @@ void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newT
// - remove unused members // - remove unused members
// - ensure remaining qualifiers/types match // - ensure remaining qualifiers/types match
TType& type = block->getWritableType(); TType& type = block->getWritableType();
#ifdef NV_EXTENSIONS
// if gl_PerVertex is redeclared for the purpose of passing through "gl_Position"
// for passthrough purpose, the redclared block should have the same qualifers as
// the current one
if (currentBlockQualifier.layoutPassthrough)
{
type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough;
type.getQualifier().storage = currentBlockQualifier.storage;
type.getQualifier().layoutStream = currentBlockQualifier.layoutStream;
type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
}
#endif
TTypeList::iterator member = type.getWritableStruct()->begin(); TTypeList::iterator member = type.getWritableStruct()->begin();
size_t numOriginalMembersFound = 0; size_t numOriginalMembersFound = 0;
while (member != type.getStruct()->end()) { while (member != type.getStruct()->end()) {
@ -3928,6 +3946,14 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
publicType.shaderQualifiers.geometry = ElgTriangleStrip; publicType.shaderQualifiers.geometry = ElgTriangleStrip;
return; return;
} }
#ifdef NV_EXTENSIONS
if (id == "passthrough") {
requireExtensions(loc, 1, &E_SPV_NV_geometry_shader_passthrough, "geometry shader passthrough");
publicType.qualifier.layoutPassthrough = true;
intermediate.setGeoPassthroughEXT();
return;
}
#endif
} else { } else {
assert(language == EShLangTessEvaluation); assert(language == EShLangTessEvaluation);
@ -4328,6 +4354,11 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
if (src.layoutPushConstant) if (src.layoutPushConstant)
dst.layoutPushConstant = true; dst.layoutPushConstant = true;
#ifdef NV_EXTENSIONS
if (src.layoutPassthrough)
dst.layoutPassthrough = true;
#endif
} }
} }

View File

@ -197,6 +197,7 @@ void TParseVersions::initializeExtensionBehavior()
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
extensionBehavior[E_GL_NV_sample_mask_override_coverage] = EBhDisable; extensionBehavior[E_GL_NV_sample_mask_override_coverage] = EBhDisable;
extensionBehavior[E_SPV_NV_geometry_shader_passthrough] = EBhDisable;
#endif #endif
// AEP // AEP
@ -309,6 +310,7 @@ void TParseVersions::getPreamble(std::string& preamble)
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
"#define GL_NV_sample_mask_override_coverage 1\n" "#define GL_NV_sample_mask_override_coverage 1\n"
"#define GL_NV_geometry_shader_passthrough 1\n"
#endif #endif
; ;
} }

View File

@ -144,6 +144,7 @@ const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_sh
#endif #endif
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage"; const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage";
const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough";
#endif #endif
// AEP // AEP

View File

@ -469,9 +469,17 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
case EShLangGeometry: case EShLangGeometry:
if (inputPrimitive == ElgNone) if (inputPrimitive == ElgNone)
error(infoSink, "At least one shader must specify an input layout primitive"); error(infoSink, "At least one shader must specify an input layout primitive");
if (outputPrimitive == ElgNone) if (outputPrimitive == ElgNone
#ifdef NV_EXTENSIONS
&& !getGeoPassthroughEXT()
#endif
)
error(infoSink, "At least one shader must specify an output layout primitive"); error(infoSink, "At least one shader must specify an output layout primitive");
if (vertices == TQualifier::layoutNotSet) if (vertices == TQualifier::layoutNotSet
#ifdef NV_EXTENSIONS
&& !getGeoPassthroughEXT()
#endif
)
error(infoSink, "At least one shader must specify a layout(max_vertices = value)"); error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
break; break;
case EShLangFragment: case EShLangFragment:

View File

@ -153,6 +153,7 @@ public:
flattenUniformArrays(false), flattenUniformArrays(false),
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
layoutOverrideCoverage(false), layoutOverrideCoverage(false),
geoPassthroughEXT(false),
#endif #endif
useUnknownFormat(false) useUnknownFormat(false)
{ {
@ -393,6 +394,8 @@ public:
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; }
bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
#endif #endif
protected: protected:
@ -457,6 +460,7 @@ protected:
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
bool layoutOverrideCoverage; bool layoutOverrideCoverage;
bool geoPassthroughEXT;
#endif #endif
typedef std::list<TCall> TGraph; typedef std::list<TCall> TGraph;

View File

@ -216,6 +216,7 @@ INSTANTIATE_TEST_CASE_P(
"spv.forwardFun.frag", "spv.forwardFun.frag",
"spv.functionCall.frag", "spv.functionCall.frag",
"spv.functionSemantics.frag", "spv.functionSemantics.frag",
"spv.GeometryShaderPassthrough.geom",
"spv.interpOps.frag", "spv.interpOps.frag",
"spv.int64.frag", "spv.int64.frag",
"spv.layoutNested.vert", "spv.layoutNested.vert",