Skip to content

Commit a16ff31

Browse files
committed
Add support for interpolation qualifiers
1 parent 4edcf5f commit a16ff31

18 files changed

+547
-30
lines changed

include/NZSL/Ast/Compare.inl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,9 @@ namespace nzsl::Ast
298298
if (!Compare(lhs.cond, rhs.cond, params))
299299
return false;
300300

301+
if (!Compare(lhs.interp, rhs.interp, params))
302+
return false;
303+
301304
if (!Compare(lhs.locationIndex, rhs.locationIndex, params))
302305
return false;
303306

include/NZSL/Ast/Enums.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace nzsl::Ast
2626

2727
enum class AttributeType
2828
{
29+
// Next free ID: 20
2930
AutoBinding = 17, //< Incremental binding index (external block only)
3031
Author = 12, //< Module author (module statement only) - has argument version string
3132
Binding = 0, //< Binding (external var only) - has argument index
@@ -37,6 +38,7 @@ namespace nzsl::Ast
3738
Entry = 5, //< Entry point (function only) - has argument type
3839
Export = 6, //< Exported (external block, function and struct only)
3940
Feature = 15, //< Feature (module statement) - has argument feature
41+
Interp = 19, //< Interpolation (struct member only) - has argument interpolation qualifier
4042
LangVersion = 9, //< NZSL version (module statement) - has argument version string
4143
License = 14, //< Module license (module statement) - has argument version string
4244
Layout = 7, //< Struct layout (struct only) - has argument style
@@ -112,6 +114,13 @@ namespace nzsl::Ast
112114
Variable
113115
};
114116

117+
enum class InterpolationQualifier
118+
{
119+
Flat = 0,
120+
NoPerspective = 1,
121+
Smooth = 2
122+
};
123+
115124
enum class IntrinsicType
116125
{
117126
// Next free index: 48

include/NZSL/Ast/ExpressionType.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ namespace nzsl::Ast
227227
struct StructMember
228228
{
229229
ExpressionValue<BuiltinEntry> builtin;
230+
ExpressionValue<InterpolationQualifier> interp;
230231
ExpressionValue<bool> cond;
231232
ExpressionValue<std::uint32_t> locationIndex;
232233
ExpressionValue<ExpressionType> type;

include/NZSL/GlslWriter.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ namespace nzsl
7373
void Append(const Ast::ExpressionType& type);
7474
void Append(const Ast::ExpressionValue<Ast::ExpressionType>& type);
7575
void Append(const Ast::FunctionType& functionType);
76+
void Append(Ast::InterpolationQualifier interpolation);
7677
void Append(const Ast::IntrinsicFunctionType& intrinsicFunctionType);
7778
void Append(const Ast::MatrixType& matrixType);
7879
void Append(const Ast::MethodType& methodType);

include/NZSL/LangWriter.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ namespace nzsl
5151
struct EarlyFragmentTestsAttribute;
5252
struct EntryAttribute;
5353
struct FeatureAttribute;
54+
struct InterpAttribute;
5455
struct LangVersionAttribute;
5556
struct LayoutAttribute;
5657
struct LicenseAttribute;
@@ -94,6 +95,7 @@ namespace nzsl
9495
void AppendAttribute(EarlyFragmentTestsAttribute attribute);
9596
void AppendAttribute(EntryAttribute attribute);
9697
void AppendAttribute(FeatureAttribute attribute);
98+
void AppendAttribute(InterpAttribute attribute);
9799
void AppendAttribute(LangVersionAttribute attribute);
98100
void AppendAttribute(LayoutAttribute attribute);
99101
void AppendAttribute(LicenseAttribute attribute);

include/NZSL/Parser.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace nzsl
2727
static std::string_view ToString(Ast::AttributeType attributeType);
2828
static std::string_view ToString(Ast::BuiltinEntry builtinEntry);
2929
static std::string_view ToString(Ast::DepthWriteMode depthWriteMode);
30+
static std::string_view ToString(Ast::InterpolationQualifier interpolationQualifier);
3031
static std::string_view ToString(Ast::LoopUnroll loopUnroll);
3132
static std::string_view ToString(Ast::MemoryLayout memoryLayout);
3233
static std::string_view ToString(Ast::ModuleFeature moduleFeature);

src/NZSL/Ast/AstSerializer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace nzsl::Ast
1212
namespace
1313
{
1414
constexpr std::uint32_t s_shaderAstMagicNumber = 0x4E534852;
15-
constexpr std::uint32_t s_shaderAstCurrentVersion = 8;
15+
constexpr std::uint32_t s_shaderAstCurrentVersion = 9;
1616

1717
class ShaderSerializerVisitor : public ExpressionVisitor, public StatementVisitor
1818
{
@@ -410,6 +410,8 @@ namespace nzsl::Ast
410410
Value(member.tag);
411411
if (IsVersionGreaterOrEqual(7))
412412
Value(member.originalName);
413+
if (IsVersionGreaterOrEqual(9))
414+
ExprValue(member.interp);
413415
}
414416
}
415417

src/NZSL/Ast/Cloner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ namespace nzsl::Ast
212212
cloneMember.type = Clone(member.type);
213213
cloneMember.builtin = Clone(member.builtin);
214214
cloneMember.cond = Clone(member.cond);
215+
cloneMember.interp = Clone(member.interp);
215216
cloneMember.locationIndex = Clone(member.locationIndex);
216217

217218
cloneMember.sourceLocation = member.sourceLocation;

src/NZSL/Ast/SanitizeVisitor.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,6 +1817,9 @@ namespace nzsl::Ast
18171817
if (member.builtin.HasValue())
18181818
ComputeExprValue(member.builtin, member.sourceLocation);
18191819

1820+
if (member.interp.HasValue())
1821+
ComputeExprValue(member.interp, member.sourceLocation);
1822+
18201823
if (member.locationIndex.HasValue())
18211824
ComputeExprValue(member.locationIndex, member.sourceLocation);
18221825

src/NZSL/GlslWriter.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,16 @@ namespace nzsl
640640
throw std::runtime_error("unexpected FunctionType");
641641
}
642642

643+
void GlslWriter::Append(Ast::InterpolationQualifier interpolation)
644+
{
645+
switch (interpolation)
646+
{
647+
case Ast::InterpolationQualifier::Flat: return Append("flat");
648+
case Ast::InterpolationQualifier::NoPerspective: return Append("noperspective");
649+
case Ast::InterpolationQualifier::Smooth: return Append("smooth");
650+
}
651+
}
652+
643653
void GlslWriter::Append(const Ast::IntrinsicFunctionType& /*intrinsicFunctionType*/)
644654
{
645655
throw std::runtime_error("unexpected intrinsic function type");
@@ -1474,8 +1484,11 @@ namespace nzsl
14741484

14751485
std::string varName = std::string(targetPrefix) + member.name;
14761486

1477-
auto OutputVariable = [&](auto&&... arg)
1487+
auto WriteVariable = [&](auto&&... arg)
14781488
{
1489+
if (member.interp.HasValue())
1490+
Append(member.interp.GetResultingValue(), " ");
1491+
14791492
Append((in) ? "in" : "out", " ");
14801493
AppendVariableDeclaration(member.type.GetResultingValue(), varName);
14811494
AppendLine(";", arg...);
@@ -1493,17 +1506,17 @@ namespace nzsl
14931506
Append(member.locationIndex.GetResultingValue());
14941507
Append(") ");
14951508

1496-
OutputVariable();
1509+
WriteVariable();
14971510
}
14981511
else
14991512
{
15001513
std::string originalName = std::move(varName);
15011514
varName = std::string(s_glslWriterVaryingPrefix) + std::to_string(member.locationIndex.GetResultingValue());
1502-
OutputVariable(" // ", originalName);
1515+
WriteVariable(" // ", originalName);
15031516
}
15041517
}
15051518
else
1506-
OutputVariable();
1519+
WriteVariable();
15071520

15081521
fields.push_back({
15091522
member.name,

src/NZSL/Lang/LangData.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace nzsl::LangData
3535
{ Ast::AttributeType::Entry, { "entry" } },
3636
{ Ast::AttributeType::Export, { "export" } },
3737
{ Ast::AttributeType::Feature, { "feature" } },
38+
{ Ast::AttributeType::Interp, { "interp" } },
3839
{ Ast::AttributeType::Layout, { "layout" } },
3940
{ Ast::AttributeType::License, { "license" } },
4041
{ Ast::AttributeType::Location, { "location" } },
@@ -92,6 +93,17 @@ namespace nzsl::LangData
9293
{ ShaderStageType::Vertex, { "vert", "vertex" }},
9394
});
9495

96+
struct InterpolationData
97+
{
98+
std::string_view identifier;
99+
};
100+
101+
constexpr auto s_interpolations = frozen::make_unordered_map<Ast::InterpolationQualifier, InterpolationData>({
102+
{ Ast::InterpolationQualifier::Flat, { "flat" } },
103+
{ Ast::InterpolationQualifier::NoPerspective, { "no_perspective" } },
104+
{ Ast::InterpolationQualifier::Smooth, { "smooth" } }
105+
});
106+
95107
namespace IntrinsicHelper
96108
{
97109
enum class ParameterType

src/NZSL/LangWriter.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ namespace nzsl
109109
bool HasValue() const { return true; }
110110
};
111111

112+
struct LangWriter::InterpAttribute
113+
{
114+
const Ast::ExpressionValue<Ast::InterpolationQualifier>& interpQualifier;
115+
116+
bool HasValue() const { return interpQualifier.HasValue(); }
117+
};
118+
112119
struct LangWriter::LangVersionAttribute
113120
{
114121
std::uint32_t version;
@@ -603,6 +610,21 @@ namespace nzsl
603610
Append(")");
604611
}
605612

613+
void LangWriter::AppendAttribute(InterpAttribute attribute)
614+
{
615+
if (!attribute.HasValue())
616+
return;
617+
618+
Append("interp(");
619+
620+
if (attribute.interpQualifier.IsResultingValue())
621+
Append(Parser::ToString(attribute.interpQualifier.GetResultingValue()));
622+
else
623+
attribute.interpQualifier.GetExpression()->Visit(*this);
624+
625+
Append(")");
626+
}
627+
606628
void LangWriter::AppendAttribute(LangVersionAttribute attribute)
607629
{
608630
std::uint32_t shaderLangVersion = attribute.version;
@@ -1438,7 +1460,7 @@ namespace nzsl
14381460

14391461
first = false;
14401462

1441-
AppendAttributes(false, CondAttribute{ member.cond }, LocationAttribute{ member.locationIndex }, BuiltinAttribute{ member.builtin }, TagAttribute{ member.tag });
1463+
AppendAttributes(false, CondAttribute{ member.cond }, LocationAttribute{ member.locationIndex }, InterpAttribute{ member.interp }, BuiltinAttribute{ member.builtin }, TagAttribute{ member.tag });
14421464
Append(member.name, ": ", member.type);
14431465
}
14441466
}

src/NZSL/Parser.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ namespace nzsl
7777
constexpr auto s_builtinMapping = BuildIdentifierMapping(LangData::s_builtinData);
7878
constexpr auto s_depthWriteMapping = BuildIdentifierMapping(LangData::s_depthWriteModes);
7979
constexpr auto s_entryPointMapping = BuildIdentifierMappingWithName(LangData::s_entryPoints);
80+
constexpr auto s_interpMapping = BuildIdentifierMapping(LangData::s_interpolations);
8081
constexpr auto s_layoutMapping = BuildIdentifierMapping(LangData::s_memoryLayouts);
8182
constexpr auto s_moduleFeatureMapping = BuildIdentifierMapping(LangData::s_moduleFeatures);
8283
constexpr auto s_unrollModeMapping = BuildIdentifierMapping(LangData::s_unrollModes);
@@ -143,6 +144,14 @@ namespace nzsl
143144
return it->second.identifier;
144145
}
145146

147+
std::string_view Parser::ToString(Ast::InterpolationQualifier interpolationQualifier)
148+
{
149+
auto it = LangData::s_interpolations.find(interpolationQualifier);
150+
assert(it != LangData::s_interpolations.end());
151+
152+
return it->second.identifier;
153+
}
154+
146155
std::string_view Parser::ToString(Ast::LoopUnroll loopUnroll)
147156
{
148157
auto it = LangData::s_unrollModes.find(loopUnroll);
@@ -1337,6 +1346,10 @@ namespace nzsl
13371346
HandleUniqueAttribute(structField.cond, std::move(attribute));
13381347
break;
13391348

1349+
case Ast::AttributeType::Interp:
1350+
HandleUniqueStringAttributeKey(structField.interp, std::move(attribute), s_interpMapping);
1351+
break;
1352+
13401353
case Ast::AttributeType::Location:
13411354
HandleUniqueAttribute(structField.locationIndex, std::move(attribute));
13421355
break;

src/NZSL/SpirV/SpirvGenData.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ namespace nzsl::SpirvGenData
5353
{ Ast::BuiltinEntry::WorkgroupIndices, { SpirvBuiltIn::WorkgroupId, SpirvCapability::Shader, SpirvVersion{ 1, 0 } } }
5454
});
5555

56+
struct SpirvInterp
57+
{
58+
SpirvDecoration interpolationDecoration;
59+
};
60+
61+
constexpr auto s_interpolationMapping = frozen::make_unordered_map<Ast::InterpolationQualifier, SpirvInterp>({
62+
{ Ast::InterpolationQualifier::Flat, { SpirvDecoration::Flat }},
63+
{ Ast::InterpolationQualifier::NoPerspective, { SpirvDecoration::NoPerspective }}
64+
// No Ast::InterpolationQualifier::Smooth since it's the default
65+
});
66+
5667
using SpirvCodeGenerator = void(SpirvAstVisitor::*)(const Ast::IntrinsicExpression& node);
5768
using SpirvGlslStd450Selector = SpirvGlslStd450Op(*)(const Ast::IntrinsicExpression& node);
5869

src/NZSL/SpirvWriter.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ namespace nzsl
5454

5555
using BuiltinDecoration = tsl::ordered_map<std::uint32_t, SpirvBuiltIn>;
5656
using ConstantVariables = std::unordered_map<std::size_t /*constIndex*/, SpirvVariable /*variable*/>;
57+
using InterpolationDecoration = tsl::ordered_map<std::uint32_t, SpirvDecoration>;
5758
using LocationDecoration = tsl::ordered_map<std::uint32_t, std::uint32_t>;
5859
using ExtInstList = tsl::ordered_set<std::string>;
5960
using ExtVarContainer = tsl::ordered_map<std::size_t /*varIndex*/, ExternalVar>;
@@ -558,6 +559,19 @@ namespace nzsl
558559
std::uint32_t varId = m_constantCache.Register(variable);
559560
locationDecorations[varId] = member.locationIndex.GetResultingValue();
560561

562+
if (member.interp.HasValue())
563+
{
564+
Ast::InterpolationQualifier interpolation = member.interp.GetResultingValue();
565+
if (interpolation != Ast::InterpolationQualifier::Smooth)
566+
{
567+
auto spvIt = SpirvGenData::s_interpolationMapping.find(member.interp.GetResultingValue());
568+
if (spvIt == SpirvGenData::s_interpolationMapping.end())
569+
throw std::runtime_error("unknown interpolation value " + std::to_string(Nz::UnderlyingCast(member.interp.GetResultingValue())));
570+
571+
interpolationDecorations[varId] = spvIt->second.interpolationDecoration;
572+
}
573+
}
574+
561575
return varId;
562576
}
563577

@@ -569,6 +583,7 @@ namespace nzsl
569583
ExtInstList extInsts;
570584
ExtVarContainer extVars;
571585
FunctionContainer funcs;
586+
InterpolationDecoration interpolationDecorations;
572587
LocationDecoration locationDecorations;
573588
StructContainer declaredStructs;
574589
tsl::ordered_set<SpirvCapability> spirvCapabilities;
@@ -789,6 +804,9 @@ namespace nzsl
789804
for (auto&& [varId, location] : previsitor.locationDecorations)
790805
state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Location, location);
791806

807+
for (auto&& [varId, interp] : previsitor.interpolationDecorations)
808+
state.annotations.Append(SpirvOp::OpDecorate, varId, interp);
809+
792810
m_currentState->constantTypeCache.Write(m_currentState->annotations, m_currentState->constants, m_currentState->debugInfo, states.debugLevel);
793811

794812
if (m_context.states->debugLevel >= DebugLevel::Minimal)

0 commit comments

Comments
 (0)