HLSL: Fix #942: Map SV_TargetN to SPV Location N.

This commit is contained in:
John Kessenich
2017-06-27 15:17:38 -06:00
parent 4f54c0c487
commit 89f8d1e64f
9 changed files with 833 additions and 9 deletions

View File

@@ -1174,7 +1174,8 @@ void HlslParseContext::flatten(const TSourceLoc& loc, const TVariable& variable)
const TType& type = variable.getType();
auto entry = flattenMap.insert(std::make_pair(variable.getUniqueId(),
TFlattenData(type.getQualifier().layoutBinding)));
TFlattenData(type.getQualifier().layoutBinding,
type.getQualifier().layoutLocation)));
// the item is a map pair, so first->second is the TFlattenData itself.
flatten(loc, variable, type, entry.first->second, "");
@@ -1236,6 +1237,19 @@ int HlslParseContext::addFlattenedMember(const TSourceLoc& loc,
if (flattenData.nextBinding != TQualifier::layoutBindingEnd)
memberVariable->getWritableType().getQualifier().layoutBinding = flattenData.nextBinding++;
if (memberVariable->getType().getQualifier().builtIn == EbvNone) {
// inherited locations must be auto bumped, not replicated
if (flattenData.nextLocation != TQualifier::layoutLocationEnd &&
memberVariable->getType().getQualifier().builtIn == EbvNone) {
memberVariable->getWritableType().getQualifier().layoutLocation = flattenData.nextLocation;
flattenData.nextLocation += intermediate.computeTypeLocationSize(memberVariable->getType());
nextOutLocation = std::max(nextOutLocation, flattenData.nextLocation);
}
} else {
// inherited locations are nonsensical for built-ins
memberVariable->getWritableType().getQualifier().layoutLocation = TQualifier::layoutLocationEnd;
}
flattenData.offsets.push_back(static_cast<int>(flattenData.members.size()));
flattenData.members.push_back(memberVariable);
@@ -1551,7 +1565,7 @@ void HlslParseContext::assignToInterface(TVariable& variable)
TType& type = variable.getWritableType();
TQualifier& qualifier = type.getQualifier();
if (qualifier.storage == EvqVaryingIn || qualifier.storage == EvqVaryingOut) {
if (qualifier.builtIn == EbvNone) {
if (qualifier.builtIn == EbvNone && !qualifier.hasLocation()) {
// Strip off the outer array dimension for those having an extra one.
int size;
if (type.isArray() && qualifier.isArrayedIo(language)) {
@@ -1991,7 +2005,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
assignToInterface(variable);
};
if (entryPointOutput)
if (entryPointOutput != nullptr)
makeVariableInOut(*entryPointOutput);
for (auto it = inputs.begin(); it != inputs.end(); ++it)
if (!isDsPcfInput((*it)->getType())) // skip domain shader PCF input (see comment below)
@@ -5211,12 +5225,27 @@ TFunction* HlslParseContext::makeConstructorCall(const TSourceLoc& loc, const TT
// Handle seeing a "COLON semantic" at the end of a type declaration,
// by updating the type according to the semantic.
//
void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBuiltInVariable builtIn, const TString& upperCase)
void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBuiltInVariable builtIn,
const TString& upperCase)
{
// adjust for stage in/out
const auto getSemanticNumber = [](const TString& semantic) -> unsigned int {
size_t pos = semantic.find_last_not_of("0123456789");
if (pos == std::string::npos)
return 0u;
return (unsigned int)atoi(semantic.c_str() + pos + 1);
};
switch(builtIn) {
case EbvNone:
// Get location numbers from fragment outputs, instead of
// auto-assigning them.
if (language == EShLangFragment && upperCase.compare(0, 9, "SV_TARGET") == 0) {
qualifier.layoutLocation = getSemanticNumber(upperCase);
nextOutLocation = std::max(nextOutLocation, qualifier.layoutLocation + 1u);
}
break;
case EbvPosition:
// adjust for stage in/out
if (language == EShLangFragment)
builtIn = EbvFragCoord;
break;

View File

@@ -213,12 +213,14 @@ public:
protected:
struct TFlattenData {
TFlattenData() : nextBinding(TQualifier::layoutBindingEnd) { }
TFlattenData(int nb) : nextBinding(nb) { }
TFlattenData() : nextBinding(TQualifier::layoutBindingEnd),
nextLocation(TQualifier::layoutLocationEnd) { }
TFlattenData(int nb, int nl) : nextBinding(nb), nextLocation(nl) { }
TVector<TVariable*> members; // individual flattened variables
TVector<int> offsets; // offset to next tree level
int nextBinding; // next binding to use.
TVector<int> offsets; // offset to next tree level
unsigned int nextBinding; // next binding to use.
unsigned int nextLocation; // next location to use
};
void fixConstInit(const TSourceLoc&, const TString& identifier, TType& type, TIntermTyped*& initializer);