From 15aba2fe81fea44969e036e181a4cf252ff41963 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Mon, 17 Jul 2017 08:58:47 -0700 Subject: Handle `flat` interpolation cases in cross compilation Fixes #104 - Map HLSL `nointerpolation` to GLSL `flat` - When lowering a `struct` type varying input/output, look for interpolation modifiers along the "chain" from the leaf field up to the original shader input variable (and take the first one found) - Not sure if this is strictly needed, but it seems like a reasonable policy - Add `flat` to varying input of integer type, with no other interpolation modifier - Note: I do *not* do anything to ignore a manually imposed interpolation modifier that might be incorrect --- source/slang/emit.cpp | 5 ++- source/slang/lower.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 88b80589a..7ffce2acd 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -2667,11 +2667,12 @@ struct EmitVisitor else if(auto mod_##TYPE = mod.As()) Emit(#KEYWORD " ") #define CASE2(TYPE, HLSL_NAME, GLSL_NAME) \ - else if(auto mod_##TYPE = mod.As()) Emit((context->shared->target == CodeGenTarget::GLSL) ? GLSL_NAME : HLSL_NAME) + else if(auto mod_##TYPE = mod.As()) Emit((context->shared->target == CodeGenTarget::GLSL) ? (#GLSL_NAME " ") : (#HLSL_NAME " ")) CASE(RowMajorLayoutModifier, row_major); CASE(ColumnMajorLayoutModifier, column_major); - CASE(HLSLNoInterpolationModifier, nointerpolation); + + CASE2(HLSLNoInterpolationModifier, nointerpolation, flat); CASE(HLSLPreciseModifier, precise); CASE(HLSLEffectSharedModifier, shared); CASE(HLSLGroupSharedModifier, groupshared); diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index caa1ab075..856da9b6c 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -7,6 +7,19 @@ namespace Slang { +struct CloneVisitor + : ModifierVisitor> +{ +#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) /* empty */ +#define SYNTAX_CLASS(NAME, BASE, ...) \ + RefPtr visit ## NAME(NAME* obj) { return new NAME(*obj); } + +#include "object-meta-begin.h" +#include "modifier-defs.h" +#include "object-meta-end.h" + +}; + // template @@ -2244,11 +2257,40 @@ struct LoweringVisitor IntVal* elementCount; }; + struct VaryingParameterVarChain + { + VaryingParameterVarChain* next = nullptr; + VarDeclBase* varDecl; + }; + + template + T* findModifier(VaryingParameterVarChain* chain) + { + for (auto c = chain; c; c = c->next) + { + auto v = c->varDecl; + if (auto mod = v->FindModifier()) + return mod; + } + return nullptr; + } + + RefPtr cloneModifier(Modifier* modifier) + { + if (!modifier) return nullptr; + + // For now we just do a shallow copy of the modifier + + CloneVisitor visitor; + return visitor.dispatch(modifier); + } + struct VaryingParameterInfo { String name; VaryingParameterDirection direction; VaryingParameterArraySpec* arraySpecs = nullptr; + VaryingParameterVarChain* varChain = nullptr; }; RefPtr createGLSLBuiltinRef( @@ -2259,6 +2301,33 @@ struct LoweringVisitor return globalVarRef; } + bool isIntegralType( + ExpressionType* type) + { + if (auto baseType = type->As()) + { + switch (baseType->BaseType) + { + default: + return false; + + case BaseType::Int: + case BaseType::UInt: + case BaseType::UInt64: + return true; + } + } + else if (auto vecType = type->As()) + { + return isIntegralType(vecType->elementType); + } + else if (auto matType = type->As()) + { + return isIntegralType(matType->getElementType()); + } + + return false; + } void lowerSimpleShaderParameterToGLSLGlobal( VaryingParameterInfo const& info, @@ -2449,6 +2518,26 @@ struct LoweringVisitor break; } + // We want to copy certain modifiers from the declaration as given, + // over to the newly created global variable. The most important + // of these is any interpolation-mode modifier. + // + // Note that a shader parameter could have been nested inside + // a `struct` type, so we will look for interpolation modifiers + // starting on the "deepest" field, and working out way out. + + // Look for interpolation mode modifier + if (auto interpolationModeModifier = findModifier(info.varChain)) + { + addModifier(globalVarDecl, cloneModifier(interpolationModeModifier)); + } + // Otherwise, check if we need to add one: + else if (isIntegralType(varType)) + { + auto mod = new HLSLNoInterpolationModifier(); + addModifier(globalVarDecl, mod); + } + RefPtr globalVarRef = new VarExpressionSyntaxNode(); globalVarRef->Position = globalVarDecl->Position; @@ -2554,8 +2643,13 @@ struct LoweringVisitor fieldExpr->declRef = fieldDeclRef; fieldExpr->BaseExpression = varExpr; + VaryingParameterVarChain fieldVarChain; + fieldVarChain.next = info.varChain; + fieldVarChain.varDecl = fieldDeclRef.getDecl(); + VaryingParameterInfo fieldInfo = info; fieldInfo.name = info.name + "_" + fieldDeclRef.GetName(); + fieldInfo.varChain = &fieldVarChain; // Need to find the layout for the given field... Decl* originalFieldDecl = nullptr; @@ -2598,9 +2692,14 @@ struct LoweringVisitor expr->declRef = declRef; expr->Type.type = GetType(declRef); + VaryingParameterVarChain varChain; + varChain.next = nullptr; + varChain.varDecl = localVarDecl; + VaryingParameterInfo info; info.name = name; info.direction = direction; + info.varChain = &varChain; // Ensure that we don't get name collisions on `inout` variables switch (direction) -- cgit v1.2.3