Skip to content

Commit

Permalink
Add support for named external block
Browse files Browse the repository at this point in the history
  • Loading branch information
NiiRoZz authored and SirLynix committed Nov 30, 2024
1 parent d8c0fa9 commit 3c93f5b
Show file tree
Hide file tree
Showing 12 changed files with 287 additions and 12 deletions.
6 changes: 6 additions & 0 deletions include/NZSL/Ast/Compare.inl
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,9 @@ namespace nzsl::Ast
if (!Compare(lhs.variableId, rhs.variableId, params))
return false;

if (!Compare(lhs.prefix, rhs.prefix, params))
return false;

return true;
}

Expand Down Expand Up @@ -609,6 +612,9 @@ namespace nzsl::Ast
if (!Compare(lhs.tag, rhs.tag, params))
return false;

if (!Compare(lhs.name, rhs.name, params))
return false;

if (!Compare(lhs.externalVars, rhs.externalVars, params))
return false;

Expand Down
2 changes: 2 additions & 0 deletions include/NZSL/Ast/Nodes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ namespace nzsl::Ast
void Visit(ExpressionVisitor& visitor) override;

std::size_t variableId;
std::string prefix;
};

struct NZSL_API UnaryExpression : Expression
Expand Down Expand Up @@ -347,6 +348,7 @@ namespace nzsl::Ast
SourceLocation sourceLocation;
};

std::string name;
std::string tag;
std::vector<ExternalVar> externalVars;
ExpressionValue<std::uint32_t> bindingSet;
Expand Down
2 changes: 2 additions & 0 deletions include/NZSL/Ast/SanitizeVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ namespace nzsl::Ast
std::size_t RegisterIntrinsic(std::string name, IntrinsicType type);
std::size_t RegisterModule(std::string moduleIdentifier, std::size_t moduleIndex);
void RegisterReservedName(std::string name);
void RegisterExternalName(std::string name, const SourceLocation& sourceLocation);
std::size_t RegisterStruct(std::string name, std::optional<StructDescription*> description, std::optional<std::size_t> index, const SourceLocation& sourceLocation);
std::size_t RegisterType(std::string name, std::optional<ExpressionType> expressionType, std::optional<std::size_t> index, const SourceLocation& sourceLocation);
std::size_t RegisterType(std::string name, std::optional<PartialType> partialType, std::optional<std::size_t> index, const SourceLocation& sourceLocation);
Expand Down Expand Up @@ -207,6 +208,7 @@ namespace nzsl::Ast
{
Alias,
Constant,
External,
Function,
Intrinsic,
Module,
Expand Down
2 changes: 2 additions & 0 deletions src/NZSL/Ast/Cloner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ namespace nzsl::Ast
clone->autoBinding = Clone(node.autoBinding);
clone->bindingSet = Clone(node.bindingSet);
clone->tag = node.tag;
clone->name = node.name;

clone->externalVars.reserve(node.externalVars.size());
for (const auto& var : node.externalVars)
Expand Down Expand Up @@ -593,6 +594,7 @@ namespace nzsl::Ast
{
auto clone = std::make_unique<VariableValueExpression>();
clone->variableId = node.variableId;
clone->prefix = node.prefix;

clone->cachedExpressionType = node.cachedExpressionType;
clone->sourceLocation = node.sourceLocation;
Expand Down
2 changes: 1 addition & 1 deletion src/NZSL/Ast/ReflectVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ namespace nzsl::Ast
for (const auto& extVar : node.externalVars)
{
if (extVar.varIndex)
m_callbacks->onVariableIndex(extVar.name, *extVar.varIndex, extVar.sourceLocation);
m_callbacks->onVariableIndex(node.name + extVar.name, *extVar.varIndex, extVar.sourceLocation);
}
}

Expand Down
49 changes: 43 additions & 6 deletions src/NZSL/Ast/SanitizeVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,12 @@ namespace nzsl::Ast

MandatoryExpr(node.expr, node.sourceLocation);

// Handle module access (TODO: Add namespace expression?)
// Handle module access and named external access (TODO: Add namespace expression?)
if (node.expr->GetType() == NodeType::IdentifierExpression && node.identifiers.size() == 1)
{
auto& identifierExpr = static_cast<IdentifierExpression&>(*node.expr);
const IdentifierData* identifierData = FindIdentifier(identifierExpr.identifier);

if (identifierData && identifierData->category == IdentifierCategory::Module)
{
std::size_t moduleIndex = m_context->moduleIndices.Retrieve(identifierData->index, node.sourceLocation);
Expand All @@ -331,6 +332,17 @@ namespace nzsl::Ast
return HandleIdentifier(identifierData, node.identifiers.front().sourceLocation);
}
}

if (identifierData && identifierData->category == IdentifierCategory::External)
{
identifierData = FindIdentifier(identifierExpr.identifier + node.identifiers.front().identifier);
if (identifierData)
{
auto variableValuePtr = HandleIdentifier(identifierData, node.identifiers.front().sourceLocation);
static_cast<VariableValueExpression*>(variableValuePtr.get())->prefix = identifierExpr.identifier;
return variableValuePtr;
}
}
}

ExpressionPtr indexedExpr = CloneExpression(node.expr);
Expand Down Expand Up @@ -1462,27 +1474,36 @@ NAZARA_WARNING_GCC_DISABLE("-Wmaybe-uninitialized")
}
};

if (!clone->name.empty())
{
RegisterExternalName(clone->name, clone->sourceLocation);
}

bool hasUnresolved = false;
Nz::StackVector<std::size_t> autoBindingEntries = NazaraStackVector(std::size_t, clone->externalVars.size());
for (std::size_t i = 0; i < clone->externalVars.size(); ++i)
{
auto& extVar = clone->externalVars[i];

SanitizeIdentifier(extVar.name, IdentifierScope::ExternalVariable);

std::string fullName = clone->name + extVar.name;

Context::UsedExternalData usedBindingData;
usedBindingData.conditionalStatementIndex = m_context->currentConditionalIndex;

if (auto it = m_context->declaredExternalVar.find(extVar.name); it != m_context->declaredExternalVar.end())
if (auto it = m_context->declaredExternalVar.find(fullName); it != m_context->declaredExternalVar.end())
{
if (it->second.conditionalStatementIndex == m_context->currentConditionalIndex || usedBindingData.conditionalStatementIndex == m_context->currentConditionalIndex)
throw CompilerExtAlreadyDeclaredError{ extVar.sourceLocation, extVar.name };
}

m_context->declaredExternalVar.emplace(extVar.name, usedBindingData);
m_context->declaredExternalVar.emplace(fullName, usedBindingData);

std::optional<ExpressionType> resolvedType = ResolveTypeExpr(extVar.type, false, node.sourceLocation);
if (!resolvedType.has_value())
{
RegisterUnresolved(extVar.name);
RegisterUnresolved(fullName);
hasUnresolved = true;
continue;
}
Expand Down Expand Up @@ -1553,8 +1574,7 @@ NAZARA_WARNING_GCC_DISABLE("-Wmaybe-uninitialized")
}

extVar.type = std::move(resolvedType).value();
extVar.varIndex = RegisterVariable(extVar.name, std::move(varType), extVar.varIndex, extVar.sourceLocation);
SanitizeIdentifier(extVar.name, IdentifierScope::ExternalVariable);
extVar.varIndex = RegisterVariable(fullName, std::move(varType), extVar.varIndex, extVar.sourceLocation);
}

// Resolve auto-binding entries when explicit binding are known
Expand Down Expand Up @@ -2866,6 +2886,9 @@ NAZARA_WARNING_POP()
return Clone(constantExpr); //< Turn ConstantExpression into ConstantValueExpression
}

case IdentifierCategory::External:
throw AstUnexpectedIdentifierError{ sourceLocation, "external" };

case IdentifierCategory::Function:
{
// Replace IdentifierExpression by FunctionExpression
Expand Down Expand Up @@ -3737,6 +3760,20 @@ NAZARA_WARNING_POP()
});
}

void SanitizeVisitor::RegisterExternalName(std::string name, const SourceLocation& sourceLocation)
{
if (!IsIdentifierAvailable(name))
throw CompilerIdentifierAlreadyUsedError{ sourceLocation, name };

m_context->currentEnv->identifiersInScope.push_back({
std::move(name),
{
std::numeric_limits<std::size_t>::max(),
IdentifierCategory::External
}
});
}

std::size_t SanitizeVisitor::RegisterStruct(std::string name, std::optional<StructDescription*> description, std::optional<std::size_t> index, const SourceLocation& sourceLocation)
{
bool unresolved = false;
Expand Down
2 changes: 1 addition & 1 deletion src/NZSL/GlslWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2267,7 +2267,7 @@ namespace nzsl
AppendComment("struct tag: " + structInfo.desc->tag);
}

std::string varName = externalVar.name + m_currentState->moduleSuffix;
std::string varName = node.name + externalVar.name + m_currentState->moduleSuffix;

// Layout handling
bool hasLayout = false;
Expand Down
13 changes: 12 additions & 1 deletion src/NZSL/LangWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,11 @@ namespace nzsl

void LangWriter::Visit(Ast::VariableValueExpression& node)
{
if (!node.prefix.empty())
{
Append(node.prefix, '.');
}

AppendIdentifier(m_currentState->variables, node.variableId);
}

Expand Down Expand Up @@ -1366,7 +1371,13 @@ namespace nzsl
void LangWriter::Visit(Ast::DeclareExternalStatement& node)
{
AppendAttributes(true, SetAttribute{ node.bindingSet }, AutoBindingAttribute{ node.autoBinding }, TagAttribute{ node.tag });
AppendLine("external");
Append("external");

if (!node.name.empty())
Append(" ", node.name);

AppendLine();

EnterScope();

bool first = true;
Expand Down
8 changes: 6 additions & 2 deletions src/NZSL/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,11 +708,15 @@ namespace nzsl
NAZARA_USE_ANONYMOUS_NAMESPACE

const Token& externalToken = Expect(Advance(), TokenType::External);
Expect(Advance(), TokenType::OpenCurlyBracket);


std::unique_ptr<Ast::DeclareExternalStatement> externalStatement = std::make_unique<Ast::DeclareExternalStatement>();
externalStatement->sourceLocation = externalToken.location;

if (const Token& peekToken = Peek(); peekToken.type == TokenType::Identifier)
externalStatement->name = ParseIdentifierAsName(nullptr);

Expect(Advance(), TokenType::OpenCurlyBracket);

Ast::ExpressionValue<bool> condition;

for (auto&& attribute : attributes)
Expand Down
2 changes: 1 addition & 1 deletion src/NZSL/SpirvWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ namespace nzsl
ExternalVar& extVarData = extVars[*extVar.varIndex];

SpirvConstantCache::Variable variable;
variable.debugName = extVar.name;
variable.debugName = node.name + extVar.name;

const Ast::ExpressionType& extVarType = extVar.type.GetResultingValue();

Expand Down
41 changes: 41 additions & 0 deletions tests/src/Tests/ErrorsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,47 @@ fn main()
}
)"), "(28,19 -> 28): CFunctionCallUnmatchingParameterType error: function GetValue parameter #0 type mismatch (expected array[struct Inner, 3], got array[uniform[struct Inner], 3])");

CHECK_THROWS_WITH(Compile(R"(
[nzsl_version("1.0")]
module;

external Viewer
{
[tag("Color map")]
[binding(0)] tex: sampler2D[f32]
}

external Viewer
{
[tag("Color map")]
[binding(1)] tex2: sampler2D[f32]
}

[entry(frag)]
fn main()
{
let value = Viewer.tex.Sample(vec2[f32](0.0, 0.0));
}
)"), "(11,1 -> 8): CIdentifierAlreadyUsed error: identifier Viewer is already used");

CHECK_THROWS_WITH(Compile(R"(
[nzsl_version("1.0")]
module;

external Viewer
{
[tag("Color map")]
[binding(0)] tex: sampler2D[f32]
}

[entry(frag)]
fn main()
{
let Viewer = 0.0;
let value = Viewer.tex.Sample(vec2[f32](0.0, 0.0));
}
)"), "(14,2 -> 18): CIdentifierAlreadyUsed error: identifier Viewer is already used");

}

/************************************************************************/
Expand Down
Loading

0 comments on commit 3c93f5b

Please sign in to comment.