@@ -32,6 +32,7 @@ ConstantIntVal* SemanticsVisitor::checkConstantIntVal(Expr* expr)
32
32
IntegerConstantExpressionCoercionType::AnyInteger,
33
33
nullptr ,
34
34
ConstantFoldingKind::CompileTime);
35
+
35
36
if (!intVal)
36
37
return nullptr ;
37
38
@@ -524,17 +525,32 @@ Modifier* SemanticsVisitor::validateAttribute(
524
525
}
525
526
526
527
// TODO(JS): Prior validation currently doesn't ensure both args are ints (as specified in
527
- // core.meta.slang), so check here to make sure they both are
528
- auto binding = checkConstantIntVal (attr->args [0 ]);
529
- auto set = checkConstantIntVal (attr->args [1 ]);
528
+ // core.meta.slang), so check here to make sure they both are.
529
+ //
530
+ // Binding attribute may also be created from GLSL style layout qualifiers where only one of
531
+ // the args are specified, hence check for each individually.
532
+ ConstantIntVal* binding = nullptr ;
533
+ if (attr->args [0 ])
534
+ binding = checkConstantIntVal (attr->args [0 ]);
535
+
536
+ ConstantIntVal* set = nullptr ;
537
+ if (attr->args [1 ])
538
+ set = checkConstantIntVal (attr->args [1 ]);
530
539
531
- if (binding == nullptr || set == nullptr )
540
+ if (! binding && ! set)
532
541
{
533
542
return nullptr ;
534
543
}
535
544
536
- bindingAttr->binding = int32_t (binding->getValue ());
537
- bindingAttr->set = int32_t (set->getValue ());
545
+ if (binding)
546
+ {
547
+ bindingAttr->binding = int32_t (binding->getValue ());
548
+ }
549
+
550
+ if (set)
551
+ {
552
+ bindingAttr->set = int32_t (set->getValue ());
553
+ }
538
554
}
539
555
else if (auto simpleLayoutAttr = as<GLSLSimpleIntegerLayoutAttribute>(attr))
540
556
{
@@ -1430,6 +1446,97 @@ bool isModifierAllowedOnDecl(bool isGLSLInput, ASTNodeType modifierType, Decl* d
1430
1446
}
1431
1447
}
1432
1448
1449
+ void GLSLBindingOffsetTracker::setBindingOffset (int binding, int64_t byteOffset)
1450
+ {
1451
+ bindingToByteOffset.set (binding, byteOffset);
1452
+ }
1453
+
1454
+ int64_t GLSLBindingOffsetTracker::getNextBindingOffset (int binding)
1455
+ {
1456
+ int64_t currentOffset;
1457
+ if (bindingToByteOffset.addIfNotExists (binding, 0 ))
1458
+ currentOffset = 0 ;
1459
+ else
1460
+ currentOffset = bindingToByteOffset.getValue (binding) + sizeof (uint32_t );
1461
+
1462
+ bindingToByteOffset.set (binding, currentOffset + sizeof (uint32_t ));
1463
+ return currentOffset;
1464
+ }
1465
+
1466
+ AttributeBase* SemanticsVisitor::checkGLSLLayoutAttribute (
1467
+ UncheckedGLSLLayoutAttribute* uncheckedAttr,
1468
+ ModifiableSyntaxNode* attrTarget)
1469
+ {
1470
+ SLANG_ASSERT (uncheckedAttr->args .getCount () == 1 );
1471
+
1472
+ Attribute* attr = nullptr ;
1473
+
1474
+ // False if the current unchecked attribute node is deleted and does not result in a new checked
1475
+ // attribute.
1476
+ bool addNode = true ;
1477
+
1478
+ if (as<UncheckedGLSLBindingLayoutAttribute>(uncheckedAttr) ||
1479
+ as<UncheckedGLSLSetLayoutAttribute>(uncheckedAttr))
1480
+ {
1481
+ // Binding and set are coupled together as a descriptor table slot resource for codegen.
1482
+ // Attempt to retrieve and annotate an existing binding attribute or create a new one.
1483
+ attr = attrTarget->findModifier <GLSLBindingAttribute>();
1484
+ if (!attr)
1485
+ {
1486
+ attr = m_astBuilder->create <GLSLBindingAttribute>();
1487
+ }
1488
+ else
1489
+ {
1490
+ addNode = false ;
1491
+ }
1492
+
1493
+ // `validateAttribute`, which will be called to parse the binding arguments, also accepts
1494
+ // modifiers from vk::binding and gl::binding where both set and binding are specified.
1495
+ // Binding is the first and set is the second argument - specify them explicitly here.
1496
+ if (as<UncheckedGLSLBindingLayoutAttribute>(uncheckedAttr))
1497
+ {
1498
+ uncheckedAttr->args .add (nullptr );
1499
+ }
1500
+ else
1501
+ {
1502
+ uncheckedAttr->args .add (uncheckedAttr->args [0 ]);
1503
+ uncheckedAttr->args [0 ] = nullptr ;
1504
+ }
1505
+
1506
+ SLANG_ASSERT (uncheckedAttr->args .getCount () == 2 );
1507
+ }
1508
+ else if (as<UncheckedGLSLOffsetLayoutAttribute>(uncheckedAttr))
1509
+ {
1510
+ attr = m_astBuilder->create <GLSLOffsetLayoutAttribute>();
1511
+ }
1512
+ else
1513
+ {
1514
+ getSink ()->diagnose (uncheckedAttr, Diagnostics::unrecognizedGLSLLayoutQualifier);
1515
+ }
1516
+
1517
+ if (attr)
1518
+ {
1519
+ attr->keywordName = uncheckedAttr->keywordName ;
1520
+ attr->originalIdentifierToken = uncheckedAttr->originalIdentifierToken ;
1521
+ attr->args = uncheckedAttr->args ;
1522
+ attr->loc = uncheckedAttr->loc ;
1523
+
1524
+ // Offset constant folding computation is deferred until all other modifiers are checked to
1525
+ // ensure bindinig is checked first.
1526
+ if (!as<GLSLOffsetLayoutAttribute>(attr))
1527
+ {
1528
+ validateAttribute (attr, nullptr , attrTarget);
1529
+ }
1530
+ }
1531
+
1532
+ if (!addNode)
1533
+ {
1534
+ attr = nullptr ;
1535
+ }
1536
+
1537
+ return attr;
1538
+ }
1539
+
1433
1540
Modifier* SemanticsVisitor::checkModifier (
1434
1541
Modifier* m,
1435
1542
ModifiableSyntaxNode* syntaxNode,
@@ -1455,6 +1562,21 @@ Modifier* SemanticsVisitor::checkModifier(
1455
1562
return checkedAttr;
1456
1563
}
1457
1564
1565
+ if (auto glslLayoutAttribute = as<UncheckedGLSLLayoutAttribute>(m))
1566
+ {
1567
+ return checkGLSLLayoutAttribute (glslLayoutAttribute, syntaxNode);
1568
+ }
1569
+
1570
+ if (const auto glslImplicitOffsetAttribute = as<GLSLImplicitOffsetLayoutAttribute>(m))
1571
+ {
1572
+ auto offsetAttr = m_astBuilder->create <GLSLOffsetLayoutAttribute>();
1573
+ offsetAttr->loc = glslImplicitOffsetAttribute->loc ;
1574
+
1575
+ // Offset constant folding computation is deferred until all other modifiers are checked to
1576
+ // ensure bindinig is checked first.
1577
+ return offsetAttr;
1578
+ }
1579
+
1458
1580
if (auto decl = as<Decl>(syntaxNode))
1459
1581
{
1460
1582
auto moduleDecl = getModuleDecl (decl);
@@ -1903,6 +2025,31 @@ void SemanticsVisitor::checkModifiers(ModifiableSyntaxNode* syntaxNode)
1903
2025
// install the new list of modifiers on the declaration
1904
2026
syntaxNode->modifiers .first = resultModifiers;
1905
2027
2028
+ // GLSL offset layout qualifiers are resolved after all other modifiers are checked to ensure
2029
+ // binding layout qualifiers are processed first.
2030
+ if (auto glslOffsetAttribute = syntaxNode->findModifier <GLSLOffsetLayoutAttribute>())
2031
+ {
2032
+ if (const auto glslBindingAttribute = syntaxNode->findModifier <GLSLBindingAttribute>())
2033
+ {
2034
+ if (glslOffsetAttribute->args .getCount () == 0 )
2035
+ {
2036
+ glslOffsetAttribute->offset = getGLSLBindingOffsetTracker ()->getNextBindingOffset (
2037
+ glslBindingAttribute->binding );
2038
+ }
2039
+ else if (const auto constVal = checkConstantIntVal (glslOffsetAttribute->args [0 ]))
2040
+ {
2041
+ glslOffsetAttribute->offset = uint64_t (constVal->getValue ());
2042
+ getGLSLBindingOffsetTracker ()->setBindingOffset (
2043
+ glslBindingAttribute->binding ,
2044
+ glslOffsetAttribute->offset );
2045
+ }
2046
+ }
2047
+ else
2048
+ {
2049
+ getSink ()->diagnose (glslOffsetAttribute, Diagnostics::missingLayoutBindingModifier);
2050
+ }
2051
+ }
2052
+
1906
2053
postProcessingOnModifiers (syntaxNode->modifiers );
1907
2054
}
1908
2055
0 commit comments