Commit e741249b by steve-lunarg

HLSL: pass tessellation execution modes through to SPIR-V

The SPIR-V generator had assumed tessellation modes such as primitive type and vertex order would only appear in tess eval (domain) shaders. SPIR-V allows either, and HLSL allows and possibly requires them to be in the hull shader. This change: 1. Passes them through for either tessellation stage, and, 2. Does not set up defaults in the domain stage for HLSl compilation, to avoid conflicting definitions.
parent e752f463
...@@ -869,14 +869,20 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls ...@@ -869,14 +869,20 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
builder.addCapability(spv::CapabilityShader); builder.addCapability(spv::CapabilityShader);
break; break;
case EShLangTessEvaluation:
case EShLangTessControl: case EShLangTessControl:
builder.addCapability(spv::CapabilityTessellation); builder.addCapability(spv::CapabilityTessellation);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
break;
case EShLangTessEvaluation: glslang::TLayoutGeometry primitive;
builder.addCapability(spv::CapabilityTessellation);
switch (glslangIntermediate->getInputPrimitive()) { if (glslangIntermediate->getStage() == EShLangTessControl) {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
primitive = glslangIntermediate->getOutputPrimitive();
} else {
primitive = glslangIntermediate->getInputPrimitive();
}
switch (primitive) {
case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break;
case glslang::ElgQuads: mode = spv::ExecutionModeQuads; break; case glslang::ElgQuads: mode = spv::ExecutionModeQuads; break;
case glslang::ElgIsolines: mode = spv::ExecutionModeIsolines; break; case glslang::ElgIsolines: mode = spv::ExecutionModeIsolines; break;
......
hlsl.hull.1.tesc hlsl.hull.1.tesc
Shader version: 450 Shader version: 450
vertices = 4 vertices = 4
vertex spacing = equal_spacing
0:? Sequence 0:? Sequence
0:26 Function Definition: @main(struct-VS_OUT-vf31[4];u1; ( temp structure{ temp 3-component vector of float cpoint}) 0:26 Function Definition: @main(struct-VS_OUT-vf31[4];u1; ( temp structure{ temp 3-component vector of float cpoint})
0:26 Function Parameters: 0:26 Function Parameters:
...@@ -115,6 +116,7 @@ Linked tessellation control stage: ...@@ -115,6 +116,7 @@ Linked tessellation control stage:
Shader version: 450 Shader version: 450
vertices = 4 vertices = 4
vertex spacing = equal_spacing
0:? Sequence 0:? Sequence
0:26 Function Definition: @main(struct-VS_OUT-vf31[4];u1; ( temp structure{ temp 3-component vector of float cpoint}) 0:26 Function Definition: @main(struct-VS_OUT-vf31[4];u1; ( temp structure{ temp 3-component vector of float cpoint})
0:26 Function Parameters: 0:26 Function Parameters:
...@@ -232,6 +234,8 @@ vertices = 4 ...@@ -232,6 +234,8 @@ vertices = 4
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint TessellationControl 4 "main" 40 44 48 66 72 92 EntryPoint TessellationControl 4 "main" 40 44 48 66 72 92
ExecutionMode 4 OutputVertices 4 ExecutionMode 4 OutputVertices 4
ExecutionMode 4 Isolines
ExecutionMode 4 SpacingEqual
Name 4 "main" Name 4 "main"
Name 8 "VS_OUT" Name 8 "VS_OUT"
MemberName 8(VS_OUT) 0 "cpoint" MemberName 8(VS_OUT) 0 "cpoint"
......
hlsl.hull.2.tesc hlsl.hull.2.tesc
Shader version: 450 Shader version: 450
vertices = 4 vertices = 4
vertex spacing = equal_spacing
0:? Sequence 0:? Sequence
0:26 Function Definition: @main(struct-VS_OUT-vf31[4]; ( temp structure{ temp 3-component vector of float cpoint}) 0:26 Function Definition: @main(struct-VS_OUT-vf31[4]; ( temp structure{ temp 3-component vector of float cpoint})
0:26 Function Parameters: 0:26 Function Parameters:
...@@ -113,6 +114,7 @@ Linked tessellation control stage: ...@@ -113,6 +114,7 @@ Linked tessellation control stage:
Shader version: 450 Shader version: 450
vertices = 4 vertices = 4
vertex spacing = equal_spacing
0:? Sequence 0:? Sequence
0:26 Function Definition: @main(struct-VS_OUT-vf31[4]; ( temp structure{ temp 3-component vector of float cpoint}) 0:26 Function Definition: @main(struct-VS_OUT-vf31[4]; ( temp structure{ temp 3-component vector of float cpoint})
0:26 Function Parameters: 0:26 Function Parameters:
...@@ -228,6 +230,8 @@ vertices = 4 ...@@ -228,6 +230,8 @@ vertices = 4
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint TessellationControl 4 "main" 42 46 48 64 66 74 94 EntryPoint TessellationControl 4 "main" 42 46 48 64 66 74 94
ExecutionMode 4 OutputVertices 4 ExecutionMode 4 OutputVertices 4
ExecutionMode 4 Isolines
ExecutionMode 4 SpacingEqual
Name 4 "main" Name 4 "main"
Name 8 "VS_OUT" Name 8 "VS_OUT"
MemberName 8(VS_OUT) 0 "cpoint" MemberName 8(VS_OUT) 0 "cpoint"
......
hlsl.hull.ctrlpt-1.tesc hlsl.hull.ctrlpt-1.tesc
Shader version: 450 Shader version: 450
vertices = 3 vertices = 3
vertex spacing = fractional_odd_spacing
triangle order = cw
0:? Sequence 0:? Sequence
0:27 Function Definition: @main(struct-hs_in_t-vf31[3];u1; ( temp structure{ temp 3-component vector of float val}) 0:27 Function Definition: @main(struct-hs_in_t-vf31[3];u1; ( temp structure{ temp 3-component vector of float val})
0:27 Function Parameters: 0:27 Function Parameters:
...@@ -200,6 +202,8 @@ Linked tessellation control stage: ...@@ -200,6 +202,8 @@ Linked tessellation control stage:
Shader version: 450 Shader version: 450
vertices = 3 vertices = 3
vertex spacing = fractional_odd_spacing
triangle order = cw
0:? Sequence 0:? Sequence
0:27 Function Definition: @main(struct-hs_in_t-vf31[3];u1; ( temp structure{ temp 3-component vector of float val}) 0:27 Function Definition: @main(struct-hs_in_t-vf31[3];u1; ( temp structure{ temp 3-component vector of float val})
0:27 Function Parameters: 0:27 Function Parameters:
...@@ -402,6 +406,9 @@ vertices = 3 ...@@ -402,6 +406,9 @@ vertices = 3
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint TessellationControl 4 "main" 41 45 48 94 108 126 EntryPoint TessellationControl 4 "main" 41 45 48 94 108 126
ExecutionMode 4 OutputVertices 3 ExecutionMode 4 OutputVertices 3
ExecutionMode 4 Triangles
ExecutionMode 4 SpacingFractionalOdd
ExecutionMode 4 VertexOrderCw
Name 4 "main" Name 4 "main"
Name 8 "hs_in_t" Name 8 "hs_in_t"
MemberName 8(hs_in_t) 0 "val" MemberName 8(hs_in_t) 0 "val"
......
hlsl.hull.void.tesc hlsl.hull.void.tesc
Shader version: 450 Shader version: 450
vertices = 3 vertices = 3
vertex spacing = fractional_even_spacing
0:? Sequence 0:? Sequence
0:26 Function Definition: @main(struct-VS_OUT-vf31[3]; ( temp structure{ temp 3-component vector of float cpoint}) 0:26 Function Definition: @main(struct-VS_OUT-vf31[3]; ( temp structure{ temp 3-component vector of float cpoint})
0:26 Function Parameters: 0:26 Function Parameters:
...@@ -55,6 +56,7 @@ Linked tessellation control stage: ...@@ -55,6 +56,7 @@ Linked tessellation control stage:
Shader version: 450 Shader version: 450
vertices = 3 vertices = 3
vertex spacing = fractional_even_spacing
0:? Sequence 0:? Sequence
0:26 Function Definition: @main(struct-VS_OUT-vf31[3]; ( temp structure{ temp 3-component vector of float cpoint}) 0:26 Function Definition: @main(struct-VS_OUT-vf31[3]; ( temp structure{ temp 3-component vector of float cpoint})
0:26 Function Parameters: 0:26 Function Parameters:
...@@ -112,6 +114,8 @@ vertices = 3 ...@@ -112,6 +114,8 @@ vertices = 3
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint TessellationControl 4 "main" 33 37 39 EntryPoint TessellationControl 4 "main" 33 37 39
ExecutionMode 4 OutputVertices 3 ExecutionMode 4 OutputVertices 3
ExecutionMode 4 Triangles
ExecutionMode 4 SpacingFractionalEven
Name 4 "main" Name 4 "main"
Name 8 "VS_OUT" Name 8 "VS_OUT"
MemberName 8(VS_OUT) 0 "cpoint" MemberName 8(VS_OUT) 0 "cpoint"
......
struct ds_in_t
{
float4 pos : POSITION;
float3 norm : TEXCOORD0;
};
struct pcf_in_t
{
float flTessFactor [3] : SV_TessFactor;
float flInsideTessFactor : SV_InsideTessFactor;
};
struct gs_in_t
{
float4 pos : POSITION;
float3 norm : TEXCOORD0;
};
[domain ( "tri" )]
gs_in_t main (const OutputPatch <ds_in_t, 3> i, float3 tesscoord : SV_DomainLocation, pcf_in_t pcf_data )
{
gs_in_t o;
o.pos = i[0].pos + tesscoord.x;
o.norm = i[0].norm + tesscoord.y;
tesscoord.z;
return o;
}
...@@ -884,6 +884,13 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree) ...@@ -884,6 +884,13 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
case EShLangTessControl: case EShLangTessControl:
infoSink.debug << "vertices = " << vertices << "\n"; infoSink.debug << "vertices = " << vertices << "\n";
if (inputPrimitive != ElgNone)
infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
if (vertexSpacing != EvsNone)
infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n";
if (vertexOrder != EvoNone)
infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n";
break; break;
case EShLangTessEvaluation: case EShLangTessEvaluation:
......
...@@ -461,10 +461,12 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) ...@@ -461,10 +461,12 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
case EShLangTessEvaluation: case EShLangTessEvaluation:
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 (vertexSpacing == EvsNone) if (source == EShSourceGlsl) {
vertexSpacing = EvsEqual; if (vertexSpacing == EvsNone)
if (vertexOrder == EvoNone) vertexSpacing = EvsEqual;
vertexOrder = EvoCcw; if (vertexOrder == EvoNone)
vertexOrder = EvoCcw;
}
break; break;
case EShLangGeometry: case EShLangGeometry:
if (inputPrimitive == ElgNone) if (inputPrimitive == ElgNone)
......
...@@ -122,6 +122,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -122,6 +122,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.getdimensions.rw.dx10.frag", "main"}, {"hlsl.getdimensions.rw.dx10.frag", "main"},
{"hlsl.getdimensions.dx10.vert", "main"}, {"hlsl.getdimensions.dx10.vert", "main"},
{"hlsl.getsampleposition.dx10.frag", "main"}, {"hlsl.getsampleposition.dx10.frag", "main"},
{"hlsl.domain.1.tese", "main"},
{"hlsl.hull.1.tesc", "main"}, {"hlsl.hull.1.tesc", "main"},
{"hlsl.hull.2.tesc", "main"}, {"hlsl.hull.2.tesc", "main"},
{"hlsl.hull.void.tesc", "main"}, {"hlsl.hull.void.tesc", "main"},
......
...@@ -1386,7 +1386,7 @@ void HlslParseContext::trackLinkage(TSymbol& symbol) ...@@ -1386,7 +1386,7 @@ void HlslParseContext::trackLinkage(TSymbol& symbol)
// Some types require fixed array sizes in SPIR-V, but can be scalars or // Some types require fixed array sizes in SPIR-V, but can be scalars or
// arrays of sizes SPIR-V doesn't allow. For example, tessellation factors. // arrays of sizes SPIR-V doesn't allow. For example, tessellation factors.
// This creates the right size. A conversion is performed when the internal // This creates the right size. A conversion is performed when the internal
// type is copied to or from the external // type is copied to or from the external type.
void HlslParseContext::fixBuiltInArrayType(TType& type) void HlslParseContext::fixBuiltInArrayType(TType& type)
{ {
int requiredSize = 0; int requiredSize = 0;
...@@ -1600,7 +1600,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l ...@@ -1600,7 +1600,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
// Handle all [attrib] attribute for the shader entry point // Handle all [attrib] attribute for the shader entry point
void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, TFunction& userFunction, const TAttributeMap& attributes) void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const TAttributeMap& attributes)
{ {
// Handle entry-point function attributes // Handle entry-point function attributes
const TIntermAggregate* numThreads = attributes[EatNumThreads]; const TIntermAggregate* numThreads = attributes[EatNumThreads];
...@@ -1779,7 +1779,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct ...@@ -1779,7 +1779,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
entryPointFunction = &userFunction; // needed in finish() entryPointFunction = &userFunction; // needed in finish()
// Handle entry point attributes // Handle entry point attributes
handleEntryPointAttributes(loc, userFunction, attributes); handleEntryPointAttributes(loc, attributes);
// entry point logic... // entry point logic...
...@@ -1853,6 +1853,9 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct ...@@ -1853,6 +1853,9 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
if (entryPointOutput) { if (entryPointOutput) {
TIntermTyped* returnAssign; TIntermTyped* returnAssign;
// For hull shaders, the wrapped entry point return value is written to
// an array element as indexed by invocation ID, which we might have to make up.
// This is required to match SPIR-V semantics.
if (language == EShLangTessControl) { if (language == EShLangTessControl) {
TIntermSymbol* invocationIdSym = findLinkageSymbol(EbvInvocationId); TIntermSymbol* invocationIdSym = findLinkageSymbol(EbvInvocationId);
......
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree); TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree);
TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&); TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&);
void handleEntryPointAttributes(const TSourceLoc&, TFunction&, const TAttributeMap&); void handleEntryPointAttributes(const TSourceLoc&, const TAttributeMap&);
void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node); void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node);
void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs); void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs);
void remapNonEntryPointIO(TFunction& function); void remapNonEntryPointIO(TFunction& function);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment