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.
This commit is contained in:
steve-lunarg
2017-04-03 09:27:53 -06:00
parent fa84001ad7
commit f38cca3ccf
4 changed files with 476 additions and 1 deletions

View File

@@ -1770,6 +1770,15 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
//
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 (userFunction.getName().compare(intermediate.getEntryPointName().c_str()) != 0) {
remapNonEntryPointIO(userFunction);
@@ -1806,10 +1815,22 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
if (entryPointOutput)
makeVariableInOut(*entryPointOutput);
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)
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
pushScope(); // matches the one in handleFunctionBody()