Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work around glslang issue 988 #142

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 126 additions & 12 deletions source/slang/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,18 @@ struct LoweringVisitor
return result;
}

RefPtr<ExpressionSyntaxNode> moveTemp(RefPtr<ExpressionSyntaxNode> expr)
{
RefPtr<Variable> varDecl = new Variable();
varDecl->Name.Content = generateName();
varDecl->Type.type = expr->Type.type;
varDecl->Expr = expr;

addDecl(varDecl);

return createVarRef(expr->Position, varDecl);
}

// The idea of this function is to take an expression that we plan to
// use/evaluate more than once, and if needed replace it with a
// reference to a temporary (initialized with the expr) so that it
Expand Down Expand Up @@ -769,14 +781,7 @@ struct LoweringVisitor
// TODO: handle the tuple cases here...

// In the general case, though, we need to introduce a temporary
RefPtr<Variable> varDecl = new Variable();
varDecl->Name.Content = generateName();
varDecl->Type.type = expr->Type.type;
varDecl->Expr = expr;

addDecl(varDecl);

return createVarRef(expr->Position, varDecl);
return moveTemp(expr);
}

// Similar to the above, this ensures that an l-value expression
Expand Down Expand Up @@ -1289,11 +1294,11 @@ struct LoweringVisitor
// Default case: just reconstrut a subscript expr
auto loweredExpr = new IndexExpressionSyntaxNode();

loweredExpr->Type.type = getSubscripResultType(baseExpr->Type.type);
loweredExpr->Type.type = getSubscripResultType(baseExpr->Type.type);

loweredExpr->BaseExpression = baseExpr;
loweredExpr->IndexExpression = indexExpr;
return loweredExpr;
loweredExpr->BaseExpression = baseExpr;
loweredExpr->IndexExpression = indexExpr;
return loweredExpr;
}
}

Expand Down Expand Up @@ -1358,6 +1363,84 @@ struct LoweringVisitor
return expr;
}

bool needGlslangBug988Workaround(
RefPtr<ExpressionSyntaxNode> inExpr)
{
switch (getTarget())
{
default:
return false;

case CodeGenTarget::GLSL:
break;
}

// There are two conditions we care about here:
//
// (1) is the *type* of the expression something that needs the WAR
// (2) does the expression reference a constant-buffer member?
//

// Issue (1): is the type of the expression something that needs the WAR?

auto exprType = inExpr->Type.type;
exprType = unwrapArray(exprType);

if (!isStructType(exprType))
return false;


// Issue (2): does the expression reference a constant-buffer member?

auto expr = inExpr;
for (;;)
{
if (auto memberRefExpr = expr.As<MemberExpressionSyntaxNode>())
{
expr = memberRefExpr->BaseExpression;
continue;
}

if (auto derefExpr = expr.As<DerefExpr>())
{
expr = derefExpr->base;
continue;
}

if (auto subscriptExpr = expr.As<IndexExpressionSyntaxNode>())
{
expr = subscriptExpr->BaseExpression;
continue;
}

break;
}

if (auto varExpr = expr.As<VarExpressionSyntaxNode>())
{
auto declRef = varExpr->declRef;
if (!declRef)
return false;

if (auto varDeclRef = declRef.As<Variable>())
{
auto varType = GetType(varDeclRef);

while (auto arrayType = varType->As<ArrayExpressionType>())
{
varType = arrayType->BaseType;
}

if (auto constantBufferType = varType->As<ConstantBufferType>())
{
return true;
}
}
}

return false;
}

void addArgs(
ExprWithArgsBase* callExpr,
RefPtr<ExpressionSyntaxNode> argExpr)
Expand All @@ -1382,6 +1465,17 @@ struct LoweringVisitor
}
else
{
// This should be the default case where we have a perfectly
// ordinary expression, but we need to work around a glslang
// but here, where passing a member of a `uniform` block
// that has `struct` type directly to a function call causes
// invalid SPIR-V to be generated.
if (needGlslangBug988Workaround(argExpr))
{
argExpr = moveTemp(argExpr);
}

// Here's the actual default case where we just add an argment
callExpr->Arguments.Add(argExpr);
}
}
Expand Down Expand Up @@ -2981,8 +3075,28 @@ struct LoweringVisitor
}
}

AggTypeDecl* isStructType(RefPtr<ExpressionType> type)
{
if (type->As<BasicExpressionType>()) return nullptr;
else if (type->As<VectorExpressionType>()) return nullptr;
else if (type->As<MatrixExpressionType>()) return nullptr;
else if (type->As<ResourceType>()) return nullptr;
else if (type->As<BuiltinGenericType>()) return nullptr;
else if (auto declRefType = type->As<DeclRefType>())
{
if (auto aggTypeDeclRef = declRefType->declRef.As<AggTypeDecl>())
{
return aggTypeDeclRef.getDecl();
}
}

return nullptr;
}

bool isImportedStructType(RefPtr<ExpressionType> type)
{
// TODO: make this use `isStructType` above

if (type->As<BasicExpressionType>()) return false;
else if (type->As<VectorExpressionType>()) return false;
else if (type->As<MatrixExpressionType>()) return false;
Expand Down
58 changes: 58 additions & 0 deletions tests/rewriter/glslang-bug-988-workaround.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#version 450
//TEST:COMPARE_GLSL:

// Test workaround for glslang issue #988
// (https://github.com/KhronosGroup/glslang/issues/988)


#if defined(__SLANG__)


__import glslang_bug_988_workaround;

uniform U
{
Foo foo;
};

vec4 doIt(Foo foo)
{
return foo.bar;
}

layout(location = 0)
out vec4 result;

void main()
{
result = doIt(foo);
}

#else

struct Foo
{
vec4 bar;
};

layout(binding = 0)
uniform U
{
Foo foo;
};

vec4 doIt(Foo foo)
{
return foo.bar;
}

layout(location = 0)
out vec4 result;

void main()
{
Foo SLANG_tmp_0 = foo;
result = doIt(SLANG_tmp_0);
}

#endif
6 changes: 6 additions & 0 deletions tests/rewriter/glslang-bug-988-workaround.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//TEST_IGNORE_FILE:

struct Foo
{
float4 bar;
};
3 changes: 2 additions & 1 deletion tests/rewriter/resources-in-structs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ out vec4 color;

void main()
{
Material SLANG_tmp_0 = m;
color = evaluateMaterial(
m,
SLANG_tmp_0,
SLANG_parameterBlock_U_m_t,
SLANG_parameterBlock_U_m_s, uv);
}
Expand Down