Add shader type

This commit is contained in:
Jérôme Leclercq 2020-07-27 18:52:58 +02:00
parent 6d0a59caab
commit 59add283cf
15 changed files with 224 additions and 12 deletions

View File

@ -8,6 +8,7 @@
#define NAZARA_SHADER_AST_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Renderer/ShaderExpressionType.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <optional>
@ -27,7 +28,9 @@ namespace Nz
struct Uniform;
struct VariableBase;
ShaderAst() = default;
inline ShaderAst(ShaderStageType shaderStage);
ShaderAst(const ShaderAst&) = default;
ShaderAst(ShaderAst&&) = default;
~ShaderAst() = default;
void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector<FunctionParameter> parameters = {}, ShaderNodes::BasicType returnType = ShaderNodes::BasicType::Void);
@ -45,6 +48,7 @@ namespace Nz
inline const InputOutput& GetOutput(std::size_t i) const;
inline std::size_t GetOutputCount() const;
inline const std::vector<InputOutput>& GetOutputs() const;
inline ShaderStageType GetStage() const;
inline const Struct& GetStruct(std::size_t i) const;
inline std::size_t GetStructCount() const;
inline const std::vector<Struct>& GetStructs() const;
@ -52,6 +56,9 @@ namespace Nz
inline std::size_t GetUniformCount() const;
inline const std::vector<Uniform>& GetUniforms() const;
ShaderAst& operator=(const ShaderAst&) = default;
ShaderAst& operator=(ShaderAst&&) = default;
struct VariableBase
{
std::string name;
@ -99,6 +106,7 @@ namespace Nz
std::vector<InputOutput> m_outputs;
std::vector<Struct> m_structs;
std::vector<Uniform> m_uniforms;
ShaderStageType m_stage;
};
}

View File

@ -7,6 +7,11 @@
namespace Nz
{
inline ShaderAst::ShaderAst(ShaderStageType shaderStage) :
m_stage(shaderStage)
{
}
inline auto ShaderAst::GetFunction(std::size_t i) const -> const Function&
{
assert(i < m_functions.size());
@ -55,6 +60,11 @@ namespace Nz
return m_outputs;
}
inline ShaderStageType ShaderAst::GetStage() const
{
return m_stage;
}
inline auto ShaderAst::GetStruct(std::size_t i) const -> const Struct&
{
assert(i < m_structs.size());

View File

@ -19,8 +19,8 @@ namespace Nz
{
public:
ShaderWriter() = default;
ShaderWriter(const ShaderWriter&) = delete;
ShaderWriter(ShaderWriter&&) = delete;
ShaderWriter(const ShaderWriter&) = default;
ShaderWriter(ShaderWriter&&) = default;
virtual ~ShaderWriter();
virtual std::string Generate(const ShaderAst& shader) = 0;

View File

@ -31,6 +31,9 @@ namespace Nz
ByteStream byteStream(source, sourceSize);
auto shader = Nz::UnserializeShader(byteStream);
if (shader.GetStage() != type)
throw std::runtime_error("incompatible shader stage");
const auto& context = device.GetReferenceContext();
const auto& contextParams = context.GetParams();

View File

@ -261,6 +261,8 @@ namespace Nz
{
m_stream << s_magicNumber << s_currentVersion;
m_stream << UInt32(shader.GetStage());
auto SerializeType = [&](const ShaderExpressionType& type)
{
std::visit([&](auto&& arg)
@ -454,7 +456,10 @@ namespace Nz
if (version > s_currentVersion)
throw std::runtime_error("unsupported version");
ShaderAst shader;
UInt32 shaderStage;
m_stream >> shaderStage;
ShaderAst shader(static_cast<ShaderStageType>(shaderStage));
UInt32 structCount;
m_stream >> structCount;

View File

@ -58,6 +58,19 @@ const char* EnumToString(PrimitiveType input)
return "<Unhandled>";
}
const char* EnumToString(ShaderType type)
{
switch (type)
{
case ShaderType::NotSet: return "NotSet";
case ShaderType::Fragment: return "Fragment";
case ShaderType::Vertex: return "Vertex";
}
assert(false);
return "<Unhandled>";
}
const char* EnumToString(TextureType textureType)
{
switch (textureType)

View File

@ -42,6 +42,18 @@ enum class PrimitiveType
constexpr std::size_t PrimitiveTypeCount = static_cast<std::size_t>(PrimitiveType::Max) + 1;
enum class ShaderType
{
NotSet = -1,
Fragment,
Vertex,
Max = Vertex
};
constexpr std::size_t ShaderTypeCount = static_cast<std::size_t>(ShaderType::Max) + 1;
enum class TextureType
{
Sampler2D,
@ -56,6 +68,7 @@ template<typename T> std::optional<T> DecodeEnum(const std::string_view& str);
const char* EnumToString(BufferType bufferType);
const char* EnumToString(InputRole role);
const char* EnumToString(PrimitiveType input);
const char* EnumToString(ShaderType type);
const char* EnumToString(TextureType textureType);
std::size_t GetComponentCount(PrimitiveType type);

View File

@ -41,7 +41,8 @@ namespace
}
ShaderGraph::ShaderGraph() :
m_flowScene(BuildRegistry())
m_flowScene(BuildRegistry()),
m_type(ShaderType::NotSet)
{
m_previewModel = std::make_unique<QuadPreview>();
@ -178,6 +179,8 @@ std::size_t ShaderGraph::AddTexture(std::string name, TextureType type, std::siz
void ShaderGraph::Clear()
{
m_type = ShaderType::NotSet;
m_flowScene.clearScene();
m_flowScene.clear();
@ -198,6 +201,9 @@ void ShaderGraph::Load(const QJsonObject& data)
{
Clear();
if (auto typeOpt = DecodeEnum<ShaderType>(data["type"].toString().toStdString()))
m_type = typeOpt.value();
QJsonArray bufferArray = data["buffers"].toArray();
for (const auto& bufferDocRef : bufferArray)
{
@ -289,6 +295,7 @@ void ShaderGraph::Load(const QJsonObject& data)
QJsonObject ShaderGraph::Save()
{
QJsonObject sceneJson;
sceneJson["type"] = QString(EnumToString(m_type));
QJsonArray bufferArray;
{
@ -599,6 +606,15 @@ void ShaderGraph::UpdateTexturePreview(std::size_t textureIndex, QImage preview)
OnTexturePreviewUpdate(this, textureIndex);
}
void ShaderGraph::UpdateType(ShaderType type)
{
if (m_type != type)
{
m_type = type;
OnTypeUpdated(this);
}
}
QtNodes::NodeDataType ShaderGraph::ToNodeDataType(PrimitiveType type)
{
switch (type)
@ -649,6 +665,21 @@ Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(TextureType type)
throw std::runtime_error("Unhandled texture type");
}
Nz::ShaderStageType ShaderGraph::ToShaderStageType(ShaderType type)
{
switch (type)
{
case ShaderType::NotSet:
throw std::runtime_error("Invalid shader type");
case ShaderType::Fragment: return Nz::ShaderStageType::Fragment;
case ShaderType::Vertex: return Nz::ShaderStageType::Vertex;
}
assert(false);
throw std::runtime_error("Unhandled shader type");
}
std::shared_ptr<QtNodes::DataModelRegistry> ShaderGraph::BuildRegistry()
{
auto registry = std::make_shared<QtNodes::DataModelRegistry>();

View File

@ -4,6 +4,7 @@
#define NAZARA_SHADERNODES_SHADERGRAPH_HPP
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/FlowScene>
#include <ShaderNode/Enums.hpp>
@ -51,6 +52,7 @@ class ShaderGraph
inline const TextureEntry& GetTexture(std::size_t textureIndex) const;
inline std::size_t GetTextureCount() const;
inline const std::vector<TextureEntry>& GetTextures() const;
inline ShaderType GetType() const;
void Load(const QJsonObject& data);
QJsonObject Save();
@ -64,6 +66,7 @@ class ShaderGraph
void UpdateStruct(std::size_t structIndex, std::string name, std::vector<StructMemberEntry> members);
void UpdateTexture(std::size_t textureIndex, std::string name, TextureType type, std::size_t bindingIndex);
void UpdateTexturePreview(std::size_t texture, QImage preview);
void UpdateType(ShaderType type);
struct BufferEntry
{
@ -121,10 +124,12 @@ class ShaderGraph
NazaraSignal(OnTextureListUpdate, ShaderGraph*);
NazaraSignal(OnTexturePreviewUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
NazaraSignal(OnTextureUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
NazaraSignal(OnTypeUpdated, ShaderGraph*);
static QtNodes::NodeDataType ToNodeDataType(PrimitiveType type);
static Nz::ShaderExpressionType ToShaderExpressionType(PrimitiveType type);
static Nz::ShaderExpressionType ToShaderExpressionType(TextureType type);
static Nz::ShaderStageType ToShaderStageType(ShaderType type);
private:
std::shared_ptr<QtNodes::DataModelRegistry> BuildRegistry();
@ -136,6 +141,7 @@ class ShaderGraph
std::vector<StructEntry> m_structs;
std::vector<TextureEntry> m_textures;
std::unique_ptr<PreviewModel> m_previewModel;
ShaderType m_type;
};
#include <ShaderNode/ShaderGraph.inl>

View File

@ -90,3 +90,8 @@ inline auto ShaderGraph::GetTextures() const -> const std::vector<TextureEntry>&
return m_textures;
}
inline ShaderType ShaderGraph::GetType() const
{
return m_type;
}

View File

@ -7,6 +7,7 @@
#include <ShaderNode/Widgets/InputEditor.hpp>
#include <ShaderNode/Widgets/OutputEditor.hpp>
#include <ShaderNode/Widgets/NodeEditor.hpp>
#include <ShaderNode/Widgets/ShaderInfoDialog.hpp>
#include <ShaderNode/Widgets/StructEditor.hpp>
#include <ShaderNode/Widgets/TextureEditor.hpp>
#include <nodes/FlowView>
@ -104,19 +105,27 @@ void MainWindow::BuildMenu()
{
QMenuBar* menu = menuBar();
QMenu* file = menu->addMenu(tr("&File"));
{
QAction* loadShader = file->addAction(tr("Load..."));
QObject::connect(loadShader, &QAction::triggered, this, &MainWindow::OnLoad);
QAction* saveShader = file->addAction(tr("Save..."));
QObject::connect(saveShader, &QAction::triggered, this, &MainWindow::OnSave);
}
QMenu* shader = menu->addMenu(tr("&Shader"));
{
QAction* loadShader = shader->addAction(tr("Load..."));
QObject::connect(loadShader, &QAction::triggered, this, &MainWindow::OnLoad);
QAction* saveShader = shader->addAction(tr("Save..."));
QObject::connect(saveShader, &QAction::triggered, this, &MainWindow::OnSave);
QAction* settings = shader->addAction(tr("Settings..."));
QObject::connect(settings, &QAction::triggered, this, &MainWindow::OnUpdateInfo);
QAction* compileShader = shader->addAction(tr("Compile..."));
QObject::connect(compileShader, &QAction::triggered, this, &MainWindow::OnCompile);
}
QMenu* generateMenu = menu->addMenu(tr("&Generate"));
QAction* generateGlsl = generateMenu->addAction(tr("GLSL"));
connect(generateGlsl, &QAction::triggered, [&](bool) { OnGenerateGLSL(); });
{
QAction* generateGlsl = generateMenu->addAction(tr("GLSL"));
connect(generateGlsl, &QAction::triggered, [&](bool) { OnGenerateGLSL(); });
}
}
void MainWindow::OnCompile()
@ -208,11 +217,27 @@ void MainWindow::OnSave()
file.write(QJsonDocument(m_shaderGraph.Save()).toJson());
}
void MainWindow::OnUpdateInfo()
{
ShaderInfo info;
info.type = m_shaderGraph.GetType();
ShaderInfoDialog* dialog = new ShaderInfoDialog(std::move(info), this);
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog]
{
ShaderInfo shaderInfo = dialog->GetShaderInfo();
m_shaderGraph.UpdateType(shaderInfo.type);
});
dialog->open();
}
Nz::ShaderAst MainWindow::ToShader()
{
Nz::ShaderNodes::StatementPtr shaderAst = m_shaderGraph.ToAst();
Nz::ShaderAst shader;
Nz::ShaderAst shader(ShaderGraph::ToShaderStageType(m_shaderGraph.GetType())); //< FIXME
for (const auto& input : m_shaderGraph.GetInputs())
shader.AddInput(input.name, m_shaderGraph.ToShaderExpressionType(input.type), input.locationIndex);

View File

@ -26,6 +26,7 @@ class MainWindow : public QMainWindow
void OnGenerateGLSL();
void OnLoad();
void OnSave();
void OnUpdateInfo();
Nz::ShaderAst ToShader();
NazaraSlot(ShaderGraph, OnSelectedNodeUpdate, m_onSelectedNodeUpdate);

View File

@ -0,0 +1,58 @@
#include <ShaderNode/Widgets/ShaderInfoDialog.hpp>
#include <ShaderNode/ShaderGraph.hpp>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QVBoxLayout>
ShaderInfoDialog::ShaderInfoDialog(QWidget* parent) :
QDialog(parent)
{
setWindowTitle(tr("Shader edit dialog"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_typeList = new QComboBox;
for (std::size_t i = 0; i < ShaderTypeCount; ++i)
m_typeList->addItem(EnumToString(static_cast<ShaderType>(i)));
QFormLayout* formLayout = new QFormLayout;
formLayout->addRow(tr("Type"), m_typeList);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &ShaderInfoDialog::OnAccept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
QVBoxLayout* verticalLayout = new QVBoxLayout;
verticalLayout->addLayout(formLayout);
verticalLayout->addWidget(buttonBox);
setLayout(verticalLayout);
}
ShaderInfoDialog::ShaderInfoDialog(const ShaderInfo& shader, QWidget* parent) :
ShaderInfoDialog(parent)
{
m_typeList->setCurrentText(QString(EnumToString(shader.type)));
}
ShaderInfo ShaderInfoDialog::GetShaderInfo() const
{
ShaderInfo bufferInfo;
bufferInfo.type = static_cast<ShaderType>(m_typeList->currentIndex());
return bufferInfo;
}
void ShaderInfoDialog::OnAccept()
{
if (m_typeList->currentIndex() < 0)
{
QMessageBox::critical(this, tr("Invalid shader type"), tr("You must select a shader type"), QMessageBox::Ok);
return;
}
accept();
}

View File

@ -0,0 +1,33 @@
#pragma once
#ifndef NAZARA_SHADERNODES_BUFFEREDITDIALOG_HPP
#define NAZARA_SHADERNODES_BUFFEREDITDIALOG_HPP
#include <ShaderNode/Enums.hpp>
#include <QtWidgets/QDialog>
class QComboBox;
struct ShaderInfo
{
ShaderType type;
};
class ShaderInfoDialog : public QDialog
{
public:
ShaderInfoDialog(QWidget* parent = nullptr);
ShaderInfoDialog(const ShaderInfo& shader, QWidget* parent = nullptr);
~ShaderInfoDialog() = default;
ShaderInfo GetShaderInfo() const;
private:
void OnAccept();
QComboBox* m_typeList;
};
#include <ShaderNode/Widgets/ShaderInfoDialog.inl>
#endif

View File

@ -0,0 +1 @@
#include <ShaderNode/Widgets/ShaderInfoDialog.hpp>