Commit f38cca3c by steve-lunarg

HLSL: handle PCF input to DS in arbitrary argument position

In the hull shader, the PCF output does not participate in an argument list, so has no defined ordering. It is always put at the end of the linkage. That means the DS input reading PCF data must be be at the end of the DS linkage as well, no matter where it may appear in the argument list. This change makes sure that happens. The detection is by looking for arguments that contain tessellation factor builtins, even as a struct member. The whole struct is taken as the PCF output if any members are so qualified.
parent fa84001a
// This will test having the PCF input to the domain shader not be given at the end of
// the argument list. We must move it to the end of the linkage in this case.
struct ds_in_t
{
float4 pos : POSITION;
float3 norm : TEXCOORD0;
};
struct pcf_in_t
{
float flTessFactor [3] : SV_TessFactor;
float flInsideTessFactor : SV_InsideTessFactor;
float foo : PCF_FOO;
};
struct gs_in_t
{
float4 pos : POSITION;
float3 norm : TEXCOORD0;
};
[domain ( "tri" )]
gs_in_t main (pcf_in_t pcf_data, const OutputPatch <ds_in_t, 3> i, float3 tesscoord : SV_DomainLocation)
{
gs_in_t o;
o.pos = i[0].pos + tesscoord.x;
o.norm = i[0].norm + tesscoord.y;
tesscoord.z;
return o;
}
...@@ -124,6 +124,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -124,6 +124,7 @@ INSTANTIATE_TEST_CASE_P(
{"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.domain.1.tese", "main"},
{"hlsl.domain.2.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"},
......
...@@ -1770,6 +1770,15 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T ...@@ -1770,6 +1770,15 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
// //
TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunction& userFunction, const TAttributeMap& attributes) TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunction& userFunction, const TAttributeMap& attributes)
{ {
// Return true if this is a tessellation patch constant function input to a domain shader.
const auto isDsPcfInput = [this](const TType& type) {
return language == EShLangTessEvaluation &&
type.contains([](const TType* t) {
return t->getQualifier().builtIn == EbvTessLevelOuter ||
t->getQualifier().builtIn == EbvTessLevelInner;
});
};
// if we aren't in the entry point, fix the IO as such and exit // if we aren't in the entry point, fix the IO as such and exit
if (userFunction.getName().compare(intermediate.getEntryPointName().c_str()) != 0) { if (userFunction.getName().compare(intermediate.getEntryPointName().c_str()) != 0) {
remapNonEntryPointIO(userFunction); remapNonEntryPointIO(userFunction);
...@@ -1806,10 +1815,22 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct ...@@ -1806,10 +1815,22 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
if (entryPointOutput) if (entryPointOutput)
makeVariableInOut(*entryPointOutput); makeVariableInOut(*entryPointOutput);
for (auto it = inputs.begin(); it != inputs.end(); ++it) for (auto it = inputs.begin(); it != inputs.end(); ++it)
makeVariableInOut(*(*it)); if (!isDsPcfInput((*it)->getType())) // skip domain shader PCF input (see comment below)
makeVariableInOut(*(*it));
for (auto it = outputs.begin(); it != outputs.end(); ++it) for (auto it = outputs.begin(); it != outputs.end(); ++it)
makeVariableInOut(*(*it)); makeVariableInOut(*(*it));
// In the domain shader, PCF input must be at the end of the linkage. That's because in the
// hull shader there is no ordering: the output comes from the separate PCF, which does not
// participate in the argument list. That is always put at the end of the HS linkage, so the
// input side of the DS must match. The argument may be in any position in the DS argument list
// however, so this ensures the linkage is built in the correct order regardless of argument order.
if (language == EShLangTessEvaluation) {
for (auto it = inputs.begin(); it != inputs.end(); ++it)
if (isDsPcfInput((*it)->getType())) // skip domain shader PCF input (see comment below)
makeVariableInOut(*(*it));
}
// Synthesize the call // Synthesize the call
pushScope(); // matches the one in handleFunctionBody() pushScope(); // matches the one in handleFunctionBody()
......
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