Shader: Add AstReflect
This commit is contained in:
parent
500ccda85a
commit
2238bbfa0c
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (C) 2020 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Shader generator"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_SHADER_AST_REFLECT_HPP
|
||||||
|
#define NAZARA_SHADER_AST_REFLECT_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Shader/Config.hpp>
|
||||||
|
#include <Nazara/Shader/Ast/AstRecursiveVisitor.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Nz::ShaderAst
|
||||||
|
{
|
||||||
|
class NAZARA_SHADER_API AstReflect : public AstRecursiveVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Callbacks;
|
||||||
|
|
||||||
|
AstReflect() = default;
|
||||||
|
AstReflect(const AstReflect&) = delete;
|
||||||
|
AstReflect(AstReflect&&) = delete;
|
||||||
|
~AstReflect() = default;
|
||||||
|
|
||||||
|
void Reflect(const StatementPtr& statement, const Callbacks& callbacks);
|
||||||
|
|
||||||
|
AstReflect& operator=(const AstReflect&) = delete;
|
||||||
|
AstReflect& operator=(AstReflect&&) = delete;
|
||||||
|
|
||||||
|
struct Callbacks
|
||||||
|
{
|
||||||
|
std::function<void(const std::string& optionName, const ExpressionType& optionType)> onOptionDeclaration;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Visit(DeclareOptionStatement& node) override;
|
||||||
|
|
||||||
|
const Callbacks* m_callbacks;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Shader/Ast/AstReflect.inl>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (C) 2020 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Shader generator"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Shader/Ast/AstReflect.hpp>
|
||||||
|
#include <Nazara/Shader/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz::ShaderAst
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Shader/DebugOff.hpp>
|
||||||
|
|
@ -5,34 +5,49 @@
|
||||||
#include <Nazara/Graphics/UberShader.hpp>
|
#include <Nazara/Graphics/UberShader.hpp>
|
||||||
#include <Nazara/Graphics/Graphics.hpp>
|
#include <Nazara/Graphics/Graphics.hpp>
|
||||||
#include <Nazara/Renderer/RenderDevice.hpp>
|
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||||
|
#include <Nazara/Shader/Ast/AstReflect.hpp>
|
||||||
|
#include <Nazara/Shader/Ast/SanitizeVisitor.hpp>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
UberShader::UberShader(ShaderStageType shaderStage, ShaderAst::StatementPtr shaderAst) :
|
UberShader::UberShader(ShaderStageType shaderStage, const ShaderAst::StatementPtr& shaderAst) :
|
||||||
m_shaderAst(std::move(shaderAst)),
|
|
||||||
m_shaderStage(shaderStage)
|
m_shaderStage(shaderStage)
|
||||||
{
|
{
|
||||||
//std::size_t conditionCount = m_shaderAst.GetConditionCount();
|
ShaderAst::SanitizeVisitor::Options options;
|
||||||
std::size_t conditionCount = 0;
|
options.removeOptionDeclaration = false;
|
||||||
|
|
||||||
if (conditionCount >= 64)
|
m_shaderAst = ShaderAst::Sanitize(shaderAst, options);
|
||||||
|
|
||||||
|
std::size_t optionCount = 0;
|
||||||
|
|
||||||
|
ShaderAst::AstReflect::Callbacks callbacks;
|
||||||
|
callbacks.onOptionDeclaration = [&](const std::string& optionName, const ShaderAst::ExpressionType& optionType)
|
||||||
|
{
|
||||||
|
m_optionIndexByName[optionName] = optionCount;
|
||||||
|
optionCount++;
|
||||||
|
};
|
||||||
|
|
||||||
|
ShaderAst::AstReflect reflect;
|
||||||
|
reflect.Reflect(m_shaderAst, callbacks);
|
||||||
|
|
||||||
|
if (optionCount >= 64)
|
||||||
throw std::runtime_error("Too many conditions");
|
throw std::runtime_error("Too many conditions");
|
||||||
|
|
||||||
m_combinationMask = std::numeric_limits<UInt64>::max();
|
m_combinationMask = std::numeric_limits<UInt64>::max();
|
||||||
m_combinationMask <<= conditionCount;
|
m_combinationMask <<= optionCount;
|
||||||
m_combinationMask = ~m_combinationMask;
|
m_combinationMask = ~m_combinationMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt64 UberShader::GetConditionFlagByName(const std::string_view& condition) const
|
UInt64 UberShader::GetOptionFlagByName(const std::string& optionName) const
|
||||||
{
|
{
|
||||||
/*std::size_t conditionIndex = m_shaderAst.FindConditionByName(condition);
|
auto it = m_optionIndexByName.find(optionName);
|
||||||
if (conditionIndex != ShaderAst::InvalidCondition)
|
if (it == m_optionIndexByName.end())
|
||||||
return SetBit<UInt64>(0, conditionIndex);
|
|
||||||
else*/
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
return SetBit<UInt64>(0, it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<ShaderModule>& UberShader::Get(UInt64 combination)
|
const std::shared_ptr<ShaderModule>& UberShader::Get(UInt64 combination)
|
||||||
|
|
@ -44,6 +59,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
ShaderWriter::States states;
|
ShaderWriter::States states;
|
||||||
states.enabledOptions = combination;
|
states.enabledOptions = combination;
|
||||||
|
states.sanitized = true;
|
||||||
|
|
||||||
std::shared_ptr<ShaderModule> stage = Graphics::Instance()->GetRenderDevice().InstantiateShaderModule(m_shaderStage, m_shaderAst, std::move(states));
|
std::shared_ptr<ShaderModule> stage = Graphics::Instance()->GetRenderDevice().InstantiateShaderModule(m_shaderStage, m_shaderAst, std::move(states));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (C) 2020 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Shader generator"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Shader/Ast/AstReflect.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <Nazara/Shader/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz::ShaderAst
|
||||||
|
{
|
||||||
|
void AstReflect::Reflect(const StatementPtr& statement, const Callbacks& callbacks)
|
||||||
|
{
|
||||||
|
assert(statement);
|
||||||
|
|
||||||
|
m_callbacks = &callbacks;
|
||||||
|
statement->Visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AstReflect::Visit(DeclareOptionStatement& node)
|
||||||
|
{
|
||||||
|
assert(m_callbacks);
|
||||||
|
if (m_callbacks->onOptionDeclaration)
|
||||||
|
m_callbacks->onOptionDeclaration(node.optName, node.optType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -113,6 +113,7 @@ namespace Nz
|
||||||
m_currentState = nullptr;
|
m_currentState = nullptr;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Always sanitize for reserved identifiers
|
||||||
ShaderAst::SanitizeVisitor::Options options;
|
ShaderAst::SanitizeVisitor::Options options;
|
||||||
options.reservedIdentifiers = {
|
options.reservedIdentifiers = {
|
||||||
// All reserved GLSL keywords as of GLSL ES 3.2
|
// All reserved GLSL keywords as of GLSL ES 3.2
|
||||||
|
|
|
||||||
|
|
@ -386,7 +386,11 @@ namespace Nz
|
||||||
|
|
||||||
std::vector<UInt32> SpirvWriter::Generate(ShaderAst::StatementPtr& shader, const States& states)
|
std::vector<UInt32> SpirvWriter::Generate(ShaderAst::StatementPtr& shader, const States& states)
|
||||||
{
|
{
|
||||||
ShaderAst::StatementPtr sanitizedAst = ShaderAst::Sanitize(shader);
|
ShaderAst::StatementPtr sanitizedAst;
|
||||||
|
if (!states.sanitized)
|
||||||
|
sanitizedAst = ShaderAst::Sanitize(shader);
|
||||||
|
|
||||||
|
ShaderAst::StatementPtr& targetAst = (states.sanitized) ? shader : sanitizedAst;
|
||||||
|
|
||||||
m_context.states = &states;
|
m_context.states = &states;
|
||||||
|
|
||||||
|
|
@ -399,7 +403,7 @@ namespace Nz
|
||||||
|
|
||||||
// Register all extended instruction sets
|
// Register all extended instruction sets
|
||||||
PreVisitor preVisitor(states, state.constantTypeCache, state.funcs);
|
PreVisitor preVisitor(states, state.constantTypeCache, state.funcs);
|
||||||
sanitizedAst->Visit(preVisitor);
|
targetAst->Visit(preVisitor);
|
||||||
|
|
||||||
m_currentState->preVisitor = &preVisitor;
|
m_currentState->preVisitor = &preVisitor;
|
||||||
|
|
||||||
|
|
@ -407,7 +411,7 @@ namespace Nz
|
||||||
state.extensionInstructions[extInst] = AllocateResultId();
|
state.extensionInstructions[extInst] = AllocateResultId();
|
||||||
|
|
||||||
SpirvAstVisitor visitor(*this, state.instructions, state.funcs);
|
SpirvAstVisitor visitor(*this, state.instructions, state.funcs);
|
||||||
sanitizedAst->Visit(visitor);
|
targetAst->Visit(visitor);
|
||||||
|
|
||||||
AppendHeader();
|
AppendHeader();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue