Commit ccb076ac by steve-lunarg

HLSL: allow non-vec3 tessellation coordinate declarations

HLSL requires vec2 tessellation coordinate declarations in some cases (e.g, isoline topology), where SPIR-V requires the TessCoord qualified builtin to be a vec3 in all cases. This alters the IO form of the variable to be a vec3, which will be copied to the shader's declared type if needed. This is not a validation; the shader type must be correct.
parent 97cb85c7
// Test vec2 tessellation coordinate: the IO form should be a vec3, copied to a vec2
// at the entry point boundary.
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 ( "isoline" )]
gs_in_t main (const OutputPatch <ds_in_t, 2> i, float2 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;
return o;
}
...@@ -125,6 +125,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -125,6 +125,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.getsampleposition.dx10.frag", "main"}, {"hlsl.getsampleposition.dx10.frag", "main"},
{"hlsl.domain.1.tese", "main"}, {"hlsl.domain.1.tese", "main"},
{"hlsl.domain.2.tese", "main"}, {"hlsl.domain.2.tese", "main"},
{"hlsl.domain.3.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"},
......
...@@ -1042,7 +1042,7 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru ...@@ -1042,7 +1042,7 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru
if (arraySizes) if (arraySizes)
ioVar->getWritableType().newArraySizes(*arraySizes); ioVar->getWritableType().newArraySizes(*arraySizes);
fixBuiltInArrayType(ioVar->getWritableType()); fixBuiltInIoType(ioVar->getWritableType());
interstageBuiltInIo[tInterstageIoData(memberType, *outerStructType)] = ioVar; interstageBuiltInIo[tInterstageIoData(memberType, *outerStructType)] = ioVar;
...@@ -1382,28 +1382,44 @@ void HlslParseContext::trackLinkage(TSymbol& symbol) ...@@ -1382,28 +1382,44 @@ 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. // type is copied to or from the external type. This corrects the externally
void HlslParseContext::fixBuiltInArrayType(TType& type) // facing input or output type to abide downstream semantics.
void HlslParseContext::fixBuiltInIoType(TType& type)
{ {
int requiredSize = 0; int requiredArraySize = 0;
switch (type.getQualifier().builtIn) { switch (type.getQualifier().builtIn) {
case EbvTessLevelOuter: requiredSize = 4; break; case EbvTessLevelOuter: requiredArraySize = 4; break;
case EbvTessLevelInner: requiredSize = 2; break; case EbvTessLevelInner: requiredArraySize = 2; break;
case EbvClipDistance: // TODO: ... case EbvClipDistance: // TODO: ...
case EbvCullDistance: // TODO: ... case EbvCullDistance: // TODO: ...
return;
case EbvTessCoord:
{
// tesscoord is always a vec3 for the IO variable, no matter the shader's
// declared vector size.
TType tessCoordType(type.getBasicType(), type.getQualifier().storage, 3);
tessCoordType.getQualifier() = type.getQualifier();
type.shallowCopy(tessCoordType);
break;
}
default: default:
return; return;
} }
if (type.isArray()) { // Alter or set array size as needed.
// Already an array. Fix the size. if (requiredArraySize > 0) {
type.changeOuterArraySize(requiredSize); if (type.isArray()) {
} else { // Already an array. Fix the size.
// it wasn't an array, but needs to be. type.changeOuterArraySize(requiredArraySize);
TArraySizes arraySizes; } else {
arraySizes.addInnerSize(requiredSize); // it wasn't an array, but needs to be.
type.newArraySizes(arraySizes); TArraySizes arraySizes;
arraySizes.addInnerSize(requiredArraySize);
type.newArraySizes(arraySizes);
}
} }
} }
...@@ -1985,6 +2001,8 @@ void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& return ...@@ -1985,6 +2001,8 @@ void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& return
} }
ioVariable->getWritableType().getQualifier().storage = storage; ioVariable->getWritableType().getQualifier().storage = storage;
fixBuiltInIoType(ioVariable->getWritableType());
return ioVariable; return ioVariable;
}; };
......
...@@ -250,7 +250,7 @@ protected: ...@@ -250,7 +250,7 @@ protected:
void addInterstageIoToLinkage(); void addInterstageIoToLinkage();
void addPatchConstantInvocation(); void addPatchConstantInvocation();
void fixBuiltInArrayType(TType&); void fixBuiltInIoType(TType&);
void flatten(const TSourceLoc& loc, const TVariable& variable); void flatten(const TSourceLoc& loc, const TVariable& variable);
int flatten(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name); int flatten(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
......
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